Railway Operation Simulator  v2.6.0
A railway simulator for Windows
InterfaceUnit.cpp
Go to the documentation of this file.
1 // InterfaceUnit.cpp
2 /*
3  BEWARE OF COMMENTS in .cpp files: they were accurate when written but have
4  sometimes been overtaken by changes and not updated
5  Comments in .h files are believed to be accurate and up to date
6 
7  This is a source code file for "railway.exe", a railway operation
8  simulator, written originally in Borland C++ Builder 4 Professional with
9  later updates in Embarcadero C++Builder 10.2.
10  Copyright (C) 2010 Albert Ball [original development]
11 
12  This program is free software: you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation, either version 3 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
25 // ---------------------------------------------------------------------------
26 
27 #include <Classes.hpp>
28 #include <Controls.hpp>
29 #include <StdCtrls.hpp>
30 #include <Forms.hpp>
31 #include <Buttons.hpp>
32 #include <ExtCtrls.hpp>
33 #include <Menus.hpp>
34 #include <Dialogs.hpp>
35 #include <Graphics.hpp>
36 #include <ComCtrls.hpp>
37 #include <fstream>
38 #include <vector>
39 #include <vcl.h>
40 #include <stdio.h>
41 #include <algorithm> //for sort
42 
43 #pragma hdrstop
44 // The above batch of include files above #pragma hdrstop appear in all .cpp files.
45 // They aren't all needed in each case but being together and identical they speed
46 // up compilation considerably (without ~14 min, with ~1 min!). They are used in
47 // conjunction with 'use pre-compiled headers' in the project compiler options.
48 
49 #include "InterfaceUnit.h"
50 #include "GraphicUnit.h"
51 #include "DisplayUnit.h"
52 #include "TextUnit.h"
53 #include "TrainUnit.h"
54 #include "Utilities.h"
55 #include "TrackUnit.h"
56 #include "AboutUnit.h"
57 #include <fstream>
58 #include <dirent.h>
59 #include <Filectrl.hpp> //to check whether directories exist
60 
61 // ---------------------------------------------------------------------------
62 #include <Vcl.HTMLHelpViewer.hpp> //added at v2.0.0 for access to the .chm help file
63 #pragma package(smart_init)
64 #pragma link "Vcl.HTMLHelpViewer" //added at v2.0.0 for access to the .chm help file
65 #pragma resource "*.dfm"
66 
68 
69 // Folder Names
70 const UnicodeString TInterface::RAILWAY_DIR_NAME = "Railways";
71 const UnicodeString TInterface::TIMETABLE_DIR_NAME = "Program timetables";
72 const UnicodeString TInterface::PERFLOG_DIR_NAME = "Performance logs";
73 const UnicodeString TInterface::SESSION_DIR_NAME = "Sessions";
74 const UnicodeString TInterface::IMAGE_DIR_NAME = "Images";
75 const UnicodeString TInterface::FORMATTEDTT_DIR_NAME = "Formatted timetables";
76 const UnicodeString TInterface::USERGRAPHICS_DIR_NAME = "Graphics";
77 
78 // ---------------------------------------------------------------------------
79 
80 __fastcall TInterface::TInterface(TComponent* Owner): TForm(Owner)
81 { // constructor
82  try
83  {
84  Screen->Cursor = TCursor(-11); // Hourglass
85  DirOpenError = false;
86  AllSetUpFlag = false; // flag to prevent MasterClock from being enabled when application activates if there has been an error during
87  // initial setup
88  // MasterClock->Enabled = false;//keep this stopped until all set up (no effect here as form not yet created, made false in object insp)
89  // Visible = false; //keep the Interface form invisible until all set up (no effect here as form not yet created, made false in object insp)
91  // use GNU Major/Minor/Patch version numbering system, change for each published modification, Dev x = interim internal
92  // development stages (don't show on published versions)
93 
94  // check for presence of directories, creation failure probably indicates that the
95  // working folder is read-only
96  CurDir = GetCurrentDir();
97  if(!DirectoryExists(RAILWAY_DIR_NAME))
98  {
99  if(!CreateDir(RAILWAY_DIR_NAME))
100  {
101  DirOpenError = true;
102  }
103  }
104  if(!DirectoryExists(TIMETABLE_DIR_NAME))
105  {
106  if(!CreateDir(TIMETABLE_DIR_NAME))
107  {
108  DirOpenError = true;
109  }
110  }
111  if(!DirectoryExists(PERFLOG_DIR_NAME))
112  {
113  if(!CreateDir(PERFLOG_DIR_NAME))
114  {
115  DirOpenError = true;
116  }
117  }
118  if(!DirectoryExists(SESSION_DIR_NAME))
119  {
120  if(!CreateDir(SESSION_DIR_NAME))
121  {
122  DirOpenError = true;
123  }
124  }
125  if(!DirectoryExists(IMAGE_DIR_NAME))
126  {
127  if(!CreateDir(IMAGE_DIR_NAME))
128  {
129  DirOpenError = true;
130  }
131  }
132  if(!DirectoryExists(FORMATTEDTT_DIR_NAME))
133  {
134  if(!CreateDir(FORMATTEDTT_DIR_NAME))
135  {
136  DirOpenError = true;
137  }
138  }
139  if(!DirectoryExists(USERGRAPHICS_DIR_NAME))
140  {
141  if(!CreateDir(USERGRAPHICS_DIR_NAME))
142  {
143  DirOpenError = true;
144  }
145  }
146  if(DirOpenError)
147  {
148  ShowMessage("Failed to create one or more of folders: " + RAILWAY_DIR_NAME + ", " + TIMETABLE_DIR_NAME + ", " + PERFLOG_DIR_NAME + ", " +
150  "program operation may be restricted");
151  }
152 
153  Application->HelpFile = AnsiString(CurDir + "\\Help.chm"); // added at v2.0.0 for .chm help file
154 
155  MainMenu1->AutoHotkeys = maManual; // Embarcadero mod: to suppress '&' inclusion for underlined characters in menu items
156  PopupMenu->AutoHotkeys = maManual; // as above
157 
158  Utilities = new TUtilities;
159  RailGraphics = new TRailGraphics();
160 
161  int DispW = (Screen->Width - 64) / 16; // will truncate down to a multiple of 16 OK here as screen dimensions are accurate
162  int DispH = (Screen->Height - 192) / 16; // Interface dimensions are 16 too wide & 14 short in height
163  MainScreen->Width = DispW * 16;
164  MainScreen->Height = DispH * 16;
165 
168  Utilities->ScreenElementWidth = DispW;
170  HiddenScreen = new TImage(Interface);
171  HiddenScreen->Width = MainScreen->Width;
172  HiddenScreen->Height = MainScreen->Height;
176  Track = new TTrack;
177  AllRoutes = new TAllRoutes;
182  SelectBitmap = new Graphics::TBitmap;
183  SelectBitmap->PixelFormat = pf8bit;
184  SelectBitmap->Transparent = true;
189  LengthWarningSentFlag = false;
190  PasteWarningSentFlag = false; //added at v2.6.0
191  FillSelectionMessageSentFlag = false; //added at v2.6.0
192  LCManualLowerBarriersMessageSent = false; //added at v2.6.0
193 
194  TrackInfoOnOffMenuItem->Caption = "Show"; // added here at v1.2.0 because dropped from ResetAll()
195  TrainStatusInfoOnOffMenuItem->Caption = "Hide Status"; // changed at v2.0.0 so normally visible
196  TrainTTInfoOnOffMenuItem->Caption = "Hide Timetable"; // as above
197  ResetAll(0);
198 
199  TempTTFileName = "";
200 
205 
206  RouteFlashDuration = 0.0;
207  PointsFlashDuration = 0.0;
208 
209  FloatingLabel->Color = clB4G5R5;
210  TrackElementPanel->Color = clB5G5R4;
211  InfoPanel->Color = clB4G5R5;
212 
213  LoadUserGraphicDialog->InitialDir = CurDir + "\\" + USERGRAPHICS_DIR_NAME; //not changeable
214 
215  Utilities->RHSignalFlag = false; // new at v2.3.0 for RH signals, always left hand on startup
216  SigsOnLeftImage1->Picture->Bitmap->LoadFromResourceName(0, "SigsOnLeft");
217  SigsOnLeftImage2->Picture->Bitmap->LoadFromResourceName(0, "SigsOnLeft");
218  SigsOnLeftImage1->Transparent = true;
219  SigsOnLeftImage2->Transparent = true;
220  SigsOnLeftImage1->Picture->Bitmap->TransparentColor = clB5G5R5;
221  SigsOnLeftImage2->Picture->Bitmap->TransparentColor = clB5G5R5;
222  SigsOnRightImage1->Picture->Bitmap->LoadFromResourceName(0, "SigsOnRight");
223  SigsOnRightImage2->Picture->Bitmap->LoadFromResourceName(0, "SigsOnRight");
224  SigsOnRightImage1->Transparent = true;
225  SigsOnRightImage2->Transparent = true;
226  SigsOnRightImage1->Picture->Bitmap->TransparentColor = clB5G5R5;
227  SigsOnRightImage2->Picture->Bitmap->TransparentColor = clB5G5R5;
228 
229  SaveRailwayDialog->InitialDir = CurDir + "\\" + RAILWAY_DIR_NAME; //default locations if not updated from Config.txt
230  LoadRailwayDialog->InitialDir = CurDir + "\\" + RAILWAY_DIR_NAME;
231  TimetableDialog->InitialDir = CurDir + "\\" + TIMETABLE_DIR_NAME;
232  SaveTTDialog->InitialDir = CurDir + "\\" + TIMETABLE_DIR_NAME;
233  LoadSessionDialog->InitialDir = CurDir + "\\" + SESSION_DIR_NAME;
234 
235  std::ifstream ConfigFile((CurDir + "\\Config.txt").c_str()); //added at v2.6.0 to set save & load directories for railways, timetables & session & to
236  if(ConfigFile.fail()) //no Config file //replace Signal.hnd, Background.col and GNU
237  {
238  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Right Hand Signals";
239  SigImagePanel->Caption = "Signals will be on the left hand side of the track";
240  SigsOnLeftImage1->Visible = true;
241  SigsOnLeftImage2->Visible = true;
242  SigsOnRightImage1->Visible = false;
243  SigsOnRightImage2->Visible = false;
244  ShowMessage(
245  "This program is free software released under the terms of the GNU General Public License Version 3, as published by the Free Software Foundation. "
246  "It may be used or redistributed in accordance with that license and is released in the hope that it will be useful, but WITHOUT ANY WARRANTY; "
247  "without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details - "
248  "you should have received a copy along with this program but if not see <http://www.gnu.org/licenses/>.");
249  }
250  else
251  {
252  AnsiString ConfigStr = "";
253  do
254  {
255  Utilities->CheckAndReadFileString(ConfigFile, ConfigStr);
256  if(ConfigFile.eof())
257  {
258  break;
259  }
260  AnsiString ConfigValue = ConfigStr.SubString(9, ConfigStr.Length() - 8);
261  if(ConfigStr.SubString(1, 8) == "Signals=")
262  {
263  if(ConfigValue == "right")
264  {
265  RailGraphics->ConvertSignalsToOppositeHand(1); // always left hand initially when start program, toggles Utilities->RHSignalFlag
266  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Left Hand Signals";
268  {
270  }
271  else
272  {
274  }
275  SigImagePanel->Caption = "Signals will be on the right hand side of the track";
276  SigsOnLeftImage1->Visible = false;
277  SigsOnLeftImage2->Visible = false;
278  SigsOnRightImage1->Visible = true;
279  SigsOnRightImage2->Visible = true;
280  }
281  else
282  {
283  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Right Hand Signals";
284  SigImagePanel->Caption = "Signals will be on the left hand side of the track";
285  SigsOnLeftImage1->Visible = true;
286  SigsOnLeftImage2->Visible = true;
287  SigsOnRightImage1->Visible = false;
288  SigsOnRightImage2->Visible = false;
289  }
290  }
291  if(ConfigStr.SubString(1, 8) == "BgndCol=")
292  {
293  // pick up transparent colour from file if there is one & set it to the stored value if it's valid else set to black
294  Utilities->clTransparent = clB0G0R0; // default black background;
295  if(ConfigValue == "white")
296  {
297  Utilities->clTransparent = TColor(0xFFFFFF);
298  }
299  else if(ConfigValue == "blue")
300  {
301  Utilities->clTransparent = TColor(0x330000);
302  }
303  }
304  if(ConfigStr.SubString(1, 8) == "RLYLocn=")
305  {
306  if(DirectoryExists(ConfigValue)) //e;se stays as original directory
307  {
308  SaveRailwayDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
309  LoadRailwayDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
310  }
311  }
312  else if(ConfigStr.SubString(1, 8) == "TTBLocn=")
313  {
314  if(DirectoryExists(ConfigValue)) //e;se stays as original directory
315  {
316  TimetableDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
317  SaveTTDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
318  }
319  }
320  else if(ConfigStr.SubString(1, 8) == "SSNLocn=")
321  {
322  if(DirectoryExists(ConfigValue)) //e;se stays as original directory
323  {
324  LoadSessionDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
325  }
326  }
327  }
328  while(!ConfigFile.eof());
329  ConfigFile.close();
330  }
331 
332  SpeedButton1->Glyph->LoadFromResourceName(0, "gl1");
333  SpeedButton2->Glyph->LoadFromResourceName(0, "gl2");
334  SpeedButton3->Glyph->LoadFromResourceName(0, "gl3");
335  SpeedButton4->Glyph->LoadFromResourceName(0, "gl4");
336  SpeedButton5->Glyph->LoadFromResourceName(0, "gl5");
337  SpeedButton6->Glyph->LoadFromResourceName(0, "gl6");
338  SpeedButton7->Glyph->LoadFromResourceName(0, "gl7");
339  SpeedButton8->Glyph->LoadFromResourceName(0, "gl8");
340  SpeedButton9->Glyph->LoadFromResourceName(0, "gl9");
341  SpeedButton10->Glyph->LoadFromResourceName(0, "gl10");
342  SpeedButton11->Glyph->LoadFromResourceName(0, "gl11");
343  SpeedButton12->Glyph->LoadFromResourceName(0, "gl12");
344  SpeedButton13->Glyph->LoadFromResourceName(0, "gl13");
345  SpeedButton14->Glyph->LoadFromResourceName(0, "gl14");
346  SpeedButton15->Glyph->LoadFromResourceName(0, "gl15");
347  SpeedButton16->Glyph->LoadFromResourceName(0, "gl16");
348  SpeedButton18->Glyph->LoadFromResourceName(0, "gl18");
349  SpeedButton19->Glyph->LoadFromResourceName(0, "gl19");
350  SpeedButton20->Glyph->LoadFromResourceName(0, "gl20");
351  SpeedButton21->Glyph->LoadFromResourceName(0, "gl21");
352  SpeedButton22->Glyph->LoadFromResourceName(0, "gl22");
353  SpeedButton23->Glyph->LoadFromResourceName(0, "gl23");
354  SpeedButton24->Glyph->LoadFromResourceName(0, "gl24");
355  SpeedButton25->Glyph->LoadFromResourceName(0, "gl25");
356  SpeedButton26->Glyph->LoadFromResourceName(0, "gl26");
357  SpeedButton27->Glyph->LoadFromResourceName(0, "gl27");
358  SpeedButton28->Glyph->LoadFromResourceName(0, "gl28");
359  SpeedButton29->Glyph->LoadFromResourceName(0, "gl29");
360  SpeedButton30->Glyph->LoadFromResourceName(0, "gl30");
361  SpeedButton31->Glyph->LoadFromResourceName(0, "gl31");
362  SpeedButton32->Glyph->LoadFromResourceName(0, "gl32");
363  SpeedButton33->Glyph->LoadFromResourceName(0, "gl33");
364  SpeedButton34->Glyph->LoadFromResourceName(0, "gl34");
365  SpeedButton35->Glyph->LoadFromResourceName(0, "gl35");
366  SpeedButton36->Glyph->LoadFromResourceName(0, "gl36");
367  SpeedButton37->Glyph->LoadFromResourceName(0, "gl37");
368  SpeedButton38->Glyph->LoadFromResourceName(0, "gl38");
369  SpeedButton39->Glyph->LoadFromResourceName(0, "gl39");
370  SpeedButton40->Glyph->LoadFromResourceName(0, "gl40");
371  SpeedButton41->Glyph->LoadFromResourceName(0, "gl41");
372  SpeedButton42->Glyph->LoadFromResourceName(0, "gl42");
373  SpeedButton43->Glyph->LoadFromResourceName(0, "gl43");
374  SpeedButton44->Glyph->LoadFromResourceName(0, "gl44");
375  SpeedButton45->Glyph->LoadFromResourceName(0, "gl45");
376  SpeedButton46->Glyph->LoadFromResourceName(0, "gl46");
377  SpeedButton47->Glyph->LoadFromResourceName(0, "gl47");
378  SpeedButton48->Glyph->LoadFromResourceName(0, "gl48");
379  SpeedButton49->Glyph->LoadFromResourceName(0, "gl49");
380  SpeedButton50->Glyph->LoadFromResourceName(0, "gl50");
381  SpeedButton51->Glyph->LoadFromResourceName(0, "gl51");
382  SpeedButton52->Glyph->LoadFromResourceName(0, "gl52");
383  SpeedButton53->Glyph->LoadFromResourceName(0, "gl53");
384  SpeedButton54->Glyph->LoadFromResourceName(0, "gl54");
385  SpeedButton55->Glyph->LoadFromResourceName(0, "gl55");
386  SpeedButton56->Glyph->LoadFromResourceName(0, "gl56");
387  SpeedButton57->Glyph->LoadFromResourceName(0, "gl57");
388  SpeedButton58->Glyph->LoadFromResourceName(0, "gl58");
389  SpeedButton59->Glyph->LoadFromResourceName(0, "gl59");
390  SpeedButton60->Glyph->LoadFromResourceName(0, "gl60");
391  SpeedButton61->Glyph->LoadFromResourceName(0, "gl61");
392  SpeedButton62->Glyph->LoadFromResourceName(0, "gl62");
393  SpeedButton63->Glyph->LoadFromResourceName(0, "gl63");
394  SpeedButton64->Glyph->LoadFromResourceName(0, "gl64");
395  SpeedButton65->Glyph->LoadFromResourceName(0, "gl65");
396  SpeedButton66->Glyph->LoadFromResourceName(0, "gl66");
397  SpeedButton67->Glyph->LoadFromResourceName(0, "gl67");
398  SpeedButton68->Glyph->LoadFromResourceName(0, "gl68");
399  SpeedButton69->Glyph->LoadFromResourceName(0, "gl69");
400  SpeedButton70->Glyph->LoadFromResourceName(0, "gl70");
401  SpeedButton71->Glyph->LoadFromResourceName(0, "gl71");
402  SpeedButton72->Glyph->LoadFromResourceName(0, "gl72");
403  SpeedButton73->Glyph->LoadFromResourceName(0, "gl73");
404  SpeedButton74->Glyph->LoadFromResourceName(0, "gl74");
405  SpeedButton75->Glyph->LoadFromResourceName(0, "gl75");
406  SpeedButton76->Glyph->LoadFromResourceName(0, "gl76");
407  SpeedButton77->Glyph->LoadFromResourceName(0, "gl77");
408  SpeedButton78->Glyph->LoadFromResourceName(0, "gl78");
409  SpeedButton79->Glyph->LoadFromResourceName(0, "gl79");
410  SpeedButton80->Glyph->LoadFromResourceName(0, "gl80");
411  SpeedButton81->Glyph->LoadFromResourceName(0, "gl81");
412  SpeedButton82->Glyph->LoadFromResourceName(0, "gl82");
413  SpeedButton83->Glyph->LoadFromResourceName(0, "gl83");
414  SpeedButton84->Glyph->LoadFromResourceName(0, "gl84");
415  SpeedButton85->Glyph->LoadFromResourceName(0, "gl85");
416  SpeedButton86->Glyph->LoadFromResourceName(0, "gl86");
417  SpeedButton87->Glyph->LoadFromResourceName(0, "gl87");
418  SpeedButton88->Glyph->LoadFromResourceName(0, "gl88set");
419  SpeedButton89->Glyph->LoadFromResourceName(0, "gl89set");
420  SpeedButton90->Glyph->LoadFromResourceName(0, "gl90set");
421  SpeedButton91->Glyph->LoadFromResourceName(0, "gl91set");
422  SpeedButton92->Glyph->LoadFromResourceName(0, "gl92set");
423  SpeedButton93->Glyph->LoadFromResourceName(0, "gl93set");
424  SpeedButton94->Glyph->LoadFromResourceName(0, "gl94set");
425  SpeedButton95->Glyph->LoadFromResourceName(0, "gl95set");
426  SpeedButton96->Glyph->LoadFromResourceName(0, "ConcourseGlyph");
427  SpeedButton97->Glyph->LoadFromResourceName(0, "gl97");
428  SpeedButton98->Glyph->LoadFromResourceName(0, "gl98");
429  SpeedButton99->Glyph->LoadFromResourceName(0, "gl99");
430  SpeedButton100->Glyph->LoadFromResourceName(0, "gl100");
431  SpeedButton101->Glyph->LoadFromResourceName(0, "gl101");
432  SpeedButton102->Glyph->LoadFromResourceName(0, "gl102");
433  SpeedButton103->Glyph->LoadFromResourceName(0, "gl103");
434  SpeedButton104->Glyph->LoadFromResourceName(0, "gl104");
435  SpeedButton105->Glyph->LoadFromResourceName(0, "gl105");
436  SpeedButton106->Glyph->LoadFromResourceName(0, "gl106");
437  SpeedButton107->Glyph->LoadFromResourceName(0, "gl107");
438  SpeedButton108->Glyph->LoadFromResourceName(0, "gl108");
439  SpeedButton109->Glyph->LoadFromResourceName(0, "gl109");
440  SpeedButton110->Glyph->LoadFromResourceName(0, "gl110");
441  SpeedButton111->Glyph->LoadFromResourceName(0, "gl111");
442  SpeedButton112->Glyph->LoadFromResourceName(0, "gl112");
443  SpeedButton113->Glyph->LoadFromResourceName(0, "gl113");
444  SpeedButton114->Glyph->LoadFromResourceName(0, "gl114");
445  SpeedButton115->Glyph->LoadFromResourceName(0, "gl115");
446  SpeedButton116->Glyph->LoadFromResourceName(0, "gl116");
447  SpeedButton117->Glyph->LoadFromResourceName(0, "gl117");
448  SpeedButton118->Glyph->LoadFromResourceName(0, "gl118");
449  SpeedButton119->Glyph->LoadFromResourceName(0, "gl119");
450  SpeedButton120->Glyph->LoadFromResourceName(0, "gl120");
451  SpeedButton121->Glyph->LoadFromResourceName(0, "gl121");
452  SpeedButton122->Glyph->LoadFromResourceName(0, "gl122");
453  SpeedButton123->Glyph->LoadFromResourceName(0, "gl123");
454  SpeedButton124->Glyph->LoadFromResourceName(0, "gl124");
455  SpeedButton125->Glyph->LoadFromResourceName(0, "gl125");
456  SpeedButton126->Glyph->LoadFromResourceName(0, "gl126");
457  SpeedButton127->Glyph->LoadFromResourceName(0, "gl127");
458  SpeedButton128->Glyph->LoadFromResourceName(0, "gl128");
459  SpeedButton129->Glyph->LoadFromResourceName(0, "gl129");
460  SpeedButton130->Glyph->LoadFromResourceName(0, "gl130");
461  SpeedButton131->Glyph->LoadFromResourceName(0, "gl131");
462  SpeedButton132->Glyph->LoadFromResourceName(0, "gl132");
463  SpeedButton133->Glyph->LoadFromResourceName(0, "gl133");
464  SpeedButton134->Glyph->LoadFromResourceName(0, "gl134");
465  SpeedButton135->Glyph->LoadFromResourceName(0, "gl135");
466  SpeedButton136->Glyph->LoadFromResourceName(0, "gl136");
467  SpeedButton137->Glyph->LoadFromResourceName(0, "gl137");
468  SpeedButton138->Glyph->LoadFromResourceName(0, "gl138");
469  SpeedButton139->Glyph->LoadFromResourceName(0, "gl139");
470  SpeedButton140->Glyph->LoadFromResourceName(0, "gl140");
471  SpeedButton141->Glyph->LoadFromResourceName(0, "gl141");
472  SpeedButton142->Glyph->LoadFromResourceName(0, "gl142");
473  SpeedButton143->Glyph->LoadFromResourceName(0, "gl143");
474  SpeedButton145->Glyph->LoadFromResourceName(0, "gl145");
475  SpeedButton146->Glyph->LoadFromResourceName(0, "gl146");
476  // below not in RailGraphics
477  SpeedButton144->Glyph->LoadFromResourceName(0, "LCGlyph");
478 
479  AddPrefDirButton->Glyph->LoadFromResourceName(0, "AddPrefDir");
480  AddTextButton->Glyph->LoadFromResourceName(0, "AddText");
481  AddTrackButton->Glyph->LoadFromResourceName(0, "AddTrack");
482  AutoSigsButton->Glyph->LoadFromResourceName(0, "AutoSig");
483  CallingOnButton->Glyph->LoadFromResourceName(0, "CallingOn");
484  DeleteAllPrefDirButton->Glyph->LoadFromResourceName(0, "ClearAllPrefDir");
485  DeleteOnePrefDirButton->Glyph->LoadFromResourceName(0, "ClearOnePrefDir");
486  ExitOperationButton->Glyph->LoadFromResourceName(0, "Exit");
487  ExitPrefDirButton->Glyph->LoadFromResourceName(0, "Exit");
488  ExitTrackButton->Glyph->LoadFromResourceName(0, "Exit");
489  ExitTTModeButton->Glyph->LoadFromResourceName(0, "Exit");
490  FontButton->Glyph->LoadFromResourceName(0, "FontGraphic");
491  HomeButton->Glyph->LoadFromResourceName(0, "Home");
492  LocationNameButton->Glyph->LoadFromResourceName(0, "NameLocs");
493  MoveTextOrGraphicButton->Glyph->LoadFromResourceName(0, "MoveTextOrGraphic");
494  NewHomeButton->Glyph->LoadFromResourceName(0, "NewHome");
495  UnrestrictedButton->Glyph->LoadFromResourceName(0, "NonSig");
496  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
497  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel");
498  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
499  PresetAutoSigRoutesButton->Glyph->LoadFromResourceName(0, "PresetAutoSigRoutes");
500  RouteCancelButton->Glyph->LoadFromResourceName(0, "RouteCancel");
501  SaveRailwayPDPButton->Glyph->LoadFromResourceName(0, "SaveRailway"); // PrefDirPanel
502  SaveRailwayBaseModeButton->Glyph->LoadFromResourceName(0, "SaveRailway"); // OperatingPanel
503  SaveRailwayTBPButton->Glyph->LoadFromResourceName(0, "SaveRailway"); // TrackBuildPanel
504  SaveSessionButton->Glyph->LoadFromResourceName(0, "SaveSession");
505  ScreenDownButton->Glyph->LoadFromResourceName(0, "BlackArrowDown");
506  ScreenGridButton->Glyph->LoadFromResourceName(0, "ScreenGrid");
507  ScreenLeftButton->Glyph->LoadFromResourceName(0, "BlackArrowLeft");
508  ScreenRightButton->Glyph->LoadFromResourceName(0, "BlackArrowRight");
509  ScreenUpButton->Glyph->LoadFromResourceName(0, "BlackArrowUp");
510  SetGapsButton->Glyph->LoadFromResourceName(0, "ConnectGaps");
511  SetLengthsButton->Glyph->LoadFromResourceName(0, "SetDists");
512  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
513  SigAspectButton->Glyph->LoadFromResourceName(0, "FourAspect"); // new at version 0.6
514  SigPrefButton->Glyph->LoadFromResourceName(0, "PrefSig");
515  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision1");
516  TrackOKButton->Glyph->LoadFromResourceName(0, "Validate");
517  TTClockAdjButton->Glyph->LoadFromResourceName(0, "TTClock");
518  UserGraphicButton->Glyph->LoadFromResourceName(0, "PictureImage");
519 
520  BufferAttentionImage->Picture->Bitmap->LoadFromResourceName(0, "BufferWarning");
521  CallOnImage->Picture->Bitmap->LoadFromResourceName(0, "CallingOn");
522  CrashImage->Picture->Bitmap->LoadFromResourceName(0, "CrashWarning");
523  DerailImage->Picture->Bitmap->LoadFromResourceName(0, "DerailWarning");
524  SignalStopImage->Picture->Bitmap->LoadFromResourceName(0, "SignalStopWarning");
525  SPADImage->Picture->Bitmap->LoadFromResourceName(0, "SPADWarning");
526  TrainFailedImage->Picture->Bitmap->LoadFromResourceName(0, "TrainFailedWarning"); // new at v2.4.0
527 
528  DistanceKey->Picture->Bitmap->LoadFromResourceName(0, "DistanceKey");
529  PrefDirKey->Picture->Bitmap->LoadFromResourceName(0, "PrefDirKey");
530 
531  TrackLinkedImage->Picture->Bitmap->LoadFromResourceName(0, "TrackLinkedGraphic");
532  TrackNotLinkedImage->Picture->Bitmap->LoadFromResourceName(0, "TrackNotLinkedGraphic");
533  GapsNotSetImage->Picture->Bitmap->LoadFromResourceName(0, "GapsNotSetGraphic");
534  GapsSetImage->Picture->Bitmap->LoadFromResourceName(0, "GapsSetGraphic");
535  LocationNamesNotSetImage->Picture->Bitmap->LoadFromResourceName(0, "LocNamesNotSetGraphic");
536  LocationNamesSetImage->Picture->Bitmap->LoadFromResourceName(0, "LocNamesSetGraphic");
537 
538 /* Don't need this - load icon directly into both Interface form & Application (via Project - Options - Application - Load Icon)
539  RailwayIcon = new TPicture;
540  RailwayIcon->Icon->LoadFromResourceName(0, "Icon1.ico");
541  Icon = RailwayIcon->Icon;
542  Application->Icon = RailwayIcon->Icon;
543 */
544 
545  AnsiString NL = '\n';
546  const AnsiString TTLabelStr1 = "Start new train" + NL + "Start new service from a split" + NL + "Start new service from another service" + NL +
547  "Start new non-repeating shuttle finish service" + NL + "Start new shuttle train at a timetabled stop" + NL +
548  "Start new shuttle service from a feeder";
549 
550  const AnsiString TTLabelStr2 = "Pass" + NL + "Be joined by another train" + NL + "Front split" + NL + "Rear split" + NL + "Change direction of train";
551 
552  const AnsiString TTLabelStr3 = "Finish && form a new service" + NL + "Finish && join another train" + NL + "Finish && exit railway" + NL +
553  "Finish && repeat shuttle, finally remain here" + NL + "Finish && repeat shuttle, finally form a finishing service" + NL +
554  "Finish non-repeating shuttle feeder service" + NL + "Finish && remain here";
555 
556  const AnsiString TTLabelStr4 = "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL +
557  "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + " " + NL + "R";
558 
559  const AnsiString TTLabelStr5 = "HH:MM ';' Location" + NL + "HH:MM ';' HH:MM ';' Location";
560 
561  const AnsiString TTLabelStr6 = "+ rear element ID - space - front element ID [+ optional ';S']" + NL + "+ ref. of the train that splits" + NL +
562  "+ other service ref." + NL + "+ shuttle service ref." + NL + "+ rear element ID - space - front element ID ';' linked shuttle ref." + NL +
563  "+ linked shuttle service ref. ';' feeder service ref." + NL + "+ location" + NL + "+ joining train ref." + NL + "+ new service ref." + NL +
564  "+ new service ref." + NL + " " + NL + "+ new service ref." + NL + "+ ref. of train to join" + NL +
565  "+ list of valid exit element IDs (at least 1) separated by spaces" + NL + "+ linked shuttle service ref.";
566 
567  const AnsiString TTLabelStr7 = "Arrival OR departure time (program will determine which from the context) + location." + NL +
568  "Arrival time, departure time (with no events between) + location";
569 
570  const AnsiString TTLabelStr9 = "Timetable entries" + NL + "(service references etc.)";
571  const AnsiString TTLabelStr11 = "Timetable" + NL + "start time";
572 
573  const AnsiString TTLabelStr12 = "NB: WITHIN SERVICES commas must" + NL + "not be used (have special meanings)," + NL +
574  "and semicolons may only be used to" + NL + "separate service components.";
575 
576  const AnsiString TTLabelStr13 = "+ linked shuttle service ref. ';' finishing service ref." + NL + "+ linked shuttle service ref.";
577 
578  const AnsiString TTLabelStr15 = "Repeat the service + ';' minutes between repeats ';' digit increment ';' number of repeats (last line of service)";
579 
580  TTLabel1->Caption = TTLabelStr1;
581  TTLabel2->Caption = TTLabelStr2;
582  TTLabel3->Caption = TTLabelStr3;
583  TTLabel4->Caption = TTLabelStr4;
584  TTLabel5->Caption = TTLabelStr5;
585  TTLabel6->Caption = TTLabelStr6;
586  TTLabel7->Caption = TTLabelStr7;
587  TTLabel9->Caption = TTLabelStr9;
588  TTLabel11->Caption = TTLabelStr11;
589  TTLabel12->Caption = TTLabelStr12;
590  TTLabel13->Caption = TTLabelStr13;
591  TTLabel15->Caption = TTLabelStr15;
592 
593  SelectBitmap->TransparentColor = Utilities->clTransparent;
594  RailGraphics->ChangeAllTransparentColours(Utilities->clTransparent, clB5G5R5); // original colour is as loaded at this stage - white
596 
597  TextBox->Color = clB3G3R3;
598  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
599  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
600 
601  if((Screen->Width < 1024) || (Screen->Height < 768))
602  {
603  ShowMessage("Please note that this program works best with a screen resolution of at least 1024 x 768. Please change if possible");
604  }
605 
606  SkipFormResizeEvent = true; // added at v2.1.0
607  MasterClock->Enabled = true;
608  Visible = true; // make Interface form visible (set to false at design time) autocalls FormResize so it is skipped
609  WindowState = wsMaximized; // need this for full screen at start autocalls FormResize so it is skipped
610  MTBFEditBox->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 30; // new v2.4.0 30 is to place it above the positional panel
611  // has to come after Visible = true or doesn't show
612  MTBFLabel->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 30 - 55; // new v2.4.0 placed above and to the left of MTBFEditBox
613  PositionalPanel->Left = MainScreen->Left + MainScreen->Width; // changed at v2.4.0
614  PositionalPanel->Top = MainScreen->Top; // changed at v2.4.0
615  PositionalPanel->Height = MainScreen->Height; // changed at v2.4.0
616  AllSetUpFlag = true;
617  MissedTicks = 0;
618  TotalTicks = 0;
620  SetLevel1Mode(131); // to reset background colour mode menu choices
621  Screen->Cursor = TCursor(-2); // Arrow
622  SkipFormResizeEvent = false; // added at v2.1.0
623  SelectedGraphicFileName = ""; // only set to null here so always has a value after use LoadUserGraphic
624 
625  FloatingPanel->Color = TColor(0xF0FFFF); // new v2.2.0, corrects floating panel background colour in Windows 10
626  PerformancePanel->Color = TColor(0xCCCCCC); // new v2.2.0 as above
627  OperatorActionPanel->Color = TColor(0xCCCCCC); // new v2.2.0 as above
628  DevelopmentPanel->Color = TColor(0xCCCCCC); // new v2.2.0 as above
629  TTStartTimeBox->Color = TColor(0x99FFFF); // cream
630  HighlightPanel->Color = TColor(0x33CCFF);
632  MTBFEditBox->Visible = false; // new at v2.4.0
633  MTBFLabel->Visible = false;
637  TTStartTimePtr = 0;
638  TTFirstServicePtr = 0;
639  TTLastServicePtr = 0;
640  Track->OverrideAndHideSignalBridgeMessage = false; //added at v2.5.1 to allow facing signals before bridges - with a warning
641  ConflictPanel->Visible = false;
642  TTClockAdjustWarningPanel->Visible = false;
643  TTClockAdjustWarningHide = false;
644  LastNonCtrlOrShiftKeyDown = -1; //set to no key
645 
646  SigImagePanel->Left = (Interface->Width - SigImagePanel->Width) / 2; // added for v2.3.0
647 
648  // below added at v2.4.0 so able to load session files with the correct decimal point
649  Utilities->DecimalPoint = '.'; // default case is full stop
650  char *LocalNumericInformation = setlocale(LC_NUMERIC, ""); // need this to set lconv to the environment's numeric format
652  if(LocalNumericInformation == "") // call failed, don't change decimal point in Utilities.cpp
653  {
654  Utilities->SetLocaleResultOK = false;
655  }
656  struct lconv Locale; // store this structure in memory (accessed via locale.h in Utilities.h)
657  struct lconv *conv = &Locale;
658  // read the locality conversion structure
659  conv = localeconv(); // this is what updates the structure
660  Utilities->DecimalPoint = conv->decimal_point[0];
661  }
662 
663  catch(const EFOpenError &e)
664  {
665  TMsgDlgButtons But;
666  But << mbOK;
667  MessageDlg(e.Message + " - program must terminate", mtError, But, 0);
668  Application->Terminate();
669  }
670 
671  catch(const Exception &e)
672  {
673  TMsgDlgButtons But;
674  But << mbOK;
675  AnsiString Message = "A fatal error occurred during the program setup process, the program must terminate. Message = " + e.Message;
676  MessageDlg(Message, mtError, But, 0); // this message given first in case can't create the error log
677  ErrorLog(115, e.Message);
678  Application->Terminate();
679  }
680 }
681 
682 // ---------------------------------------------------------------------------
683 
685 { // destructor
686  try
687  {
688  //rewrite ConfigFile with signal handedness, background colour & InitialDir values (may be same but no matter)
689  AnsiString ColourStr = "", SignalStr = "";
690  remove((CurDir + "\\Config.txt").c_str());
691  std::ofstream ConfigFile((CurDir + "\\Config.txt").c_str());
692  ColourStr = "black";
693  SignalStr = "left";
694  if(Utilities->clTransparent == TColor(0xFFFFFF))
695  {
696  ColourStr = "white";
697  }
698  else if(Utilities->clTransparent == TColor(0x330000))
699  {
700  ColourStr = "blue";
701  }
703  {
704  SignalStr = "right";
705  }
706 
707  ConfigFile << AnsiString("Signals=") << SignalStr << '\n';
708  ConfigFile << AnsiString("BgndCol=") << ColourStr << '\n';
709  ConfigFile << AnsiString("RLYLocn=") << AnsiString(LoadRailwayDialog->InitialDir) << '\n';
710  ConfigFile << AnsiString("TTBLocn=") << AnsiString(TimetableDialog->InitialDir) << '\n';
711  ConfigFile << AnsiString("SSNLocn=") << AnsiString(LoadSessionDialog->InitialDir) << '\n';
712  ConfigFile.close();
713 
714  SkipFormResizeEvent = true; // added at v2.1.0
715  delete NonSigRouteStartMarker;
716  delete SigRouteStartMarker;
717  delete AutoRouteStartMarker;
718  delete PointFlash;
719  delete SelectBitmap;
720  delete TrainController;
721  delete EveryPrefDir;
722  delete ConstructRoute;
723  delete ConstructPrefDir;
724  delete AllRoutes;
725  delete Track;
726  delete TextHandler;
727  delete HiddenDisplay;
728  delete HiddenScreen;
729  delete Display;
730  delete RailGraphics;
731  delete Utilities;
732  DeleteFile(TempTTFileName); //added after v2.4.3 to prevent temporary files building up
733  }
734  catch(const Exception &e)
735  {
736  ErrorLog(116, e.Message);
737  }
738 }
740 
741 // ---------------------------------------------------------------------------
742 
743 void __fastcall TInterface::FormCreate(TObject *Sender)
744 { // these functions have to be defined here to take effect when application activated & deactivated
745  try
746  {
747  Application->OnDeactivate = AppDeactivate;
748  Application->OnActivate = AppActivate;
749  }
750  catch(const Exception &e)
751  {
752  ErrorLog(117, e.Message);
753  }
754 }
755 
756 // ---------------------------------------------------------------------------
757 
758 void __fastcall TInterface::AppDeactivate(TObject *Sender)
759 { // pause operation if operating & stop the master clock
760  try
761  {
763  {
764  if(Track->RouteFlashFlag) // in case route building - cancels the route, freezes otherwise - reported
765  { // by Matt Blades 30/06/11
769  Screen->Cursor = TCursor(-2); // Arrow
770  Track->RouteFlashFlag = false;
771  ClearandRebuildRailway(48); // to get rid of displayed route
772  }
773  if(Track->PointFlashFlag)
774  // added at v1.3.1 to prevent lockup for flashing points when deactivates. Notified by Ian Walker in his email of 25/03/13.
775  {
777  Track->PointFlashFlag = false;
779  Screen->Cursor = TCursor(-2); // Arrow
780  }
783  }
784  MasterClock->Enabled = false;
785  }
786  catch(const Exception &e)
787  {
788  ErrorLog(118, e.Message);
789  }
790 }
791 
792 // ---------------------------------------------------------------------------
793 
794 void __fastcall TInterface::AppActivate(TObject *Sender)
795 { // restart the master clock providing Interface constructor has run
796  try
797  {
798  if(AllSetUpFlag)
799  {
800  MasterClock->Enabled = true;
801  }
802  }
803  catch(const Exception &e)
804  {
805  ErrorLog(119, e.Message);
806  }
807 }
808 
809 // ---------------------------------------------------------------------------
810 
811 UnicodeString TInterface::GetVersion()
812 {
813  DWORD VersionHandle;
814  DWORD VersionSize;
815  LPBYTE pBuffer;
816  UnicodeString strVersion = L"N/A";
817 
818  VersionSize = GetFileVersionInfoSizeW(Application->ExeName.c_str(), &VersionHandle);
819  if(VersionSize)
820  {
821  pBuffer = new BYTE[VersionSize];
822 
823  if(GetFileVersionInfoW(Application->ExeName.c_str(), VersionHandle, VersionSize, pBuffer))
824  {
825  VS_FIXEDFILEINFO *fi;
826  UINT buflen;
827 
828  // uncomment strVersion and HIWORD alternates below when future CI implemented: sas@2.1.0
829  if(VerQueryValueW(pBuffer, L"\\", (void**)&fi, &buflen))
830  {
831  // strVersion.sprintf(L"%d.%d.%d (Build %d)",
832  strVersion.sprintf(L"%d.%d.%d", HIWORD(fi->dwFileVersionMS), LOWORD(fi->dwFileVersionMS), HIWORD(fi->dwFileVersionLS)
833  // HIWORD(fi->dwFileVersionLS), LOWORD(fi->dwFileVersionLS)
834  );
835  }
836  }
837 
838  delete[]pBuffer;
839  }
840 
841  return L" v" + strVersion;
842 }
843 
844 // ---------------------------------------------------------------------------
845 // Track Build Interface
846 // ---------------------------------------------------------------------------
847 void __fastcall TInterface::BuildTrackMenuItemClick(TObject *Sender) // Mode Menu Item
848 {
849  try
850  {
851  TrainController->LogEvent("BuildTrackMenuItemClick");
852  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",BuildTrackMenuItemClick");
854  SetLevel1Mode(0);
855  Utilities->CallLogPop(1159);
856  }
857  catch(const Exception &e)
858  {
859  ErrorLog(120, e.Message);
860  }
861 }
862 // ---------------------------------------------------------------------------
863 
864 void __fastcall TInterface::AddTrackButtonClick(TObject *Sender)
865 {
866  try
867  {
868  TrainController->LogEvent("AddTrackButtonClick");
869  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddTrackButtonClick");
871  SetLevel1Mode(38);
874  Utilities->CallLogPop(1162);
875  }
876  catch(const Exception &e)
877  {
878  ErrorLog(121, e.Message);
879  }
880 }
881 
882 // ---------------------------------------------------------------------------
883 void __fastcall TInterface::SpeedButtonClick(TObject *Sender)
884 {
885  try
886  {
887  TrainController->LogEvent("SpeedButtonClick");
888  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SpeedButtonClick");
889  ReselectMenuItem->Enabled = false;
890  if(((TSpeedButton*)Sender)->Down)
891  {
892  CurrentSpeedButton = (TSpeedButton*)Sender;
893 // TrainController->LogEvent("SpeedButtonClick, " + CurrentSpeedButton->Tag); //v 1.3.1 - using non-AnsiString CurrentSpeedButton->Tag sends (for an unknown reason) a completely wrong string to LogEvent, usually "...(behind this message)"
894  TrainController->LogEvent("SpeedButtonClick, " + AnsiString(CurrentSpeedButton->Tag)); // new version //use for v1.3.2
895  if((Level2TrackMode == TrackSelecting) && (CurrentSpeedButton->Tag != 144)) //new addition at v2.6.0 to fill selected area with the element corresponding to CurrentSpeedButton
896  { //144 = level crossing & these not permitted
897  if((SelectRect.left != SelectRect.right) && (SelectRect.top != SelectRect.bottom) && SelectionValid)
898  {
899  Screen->Cursor = TCursor(-11); // Hourglass;
900  InfoPanel->Caption = "SELECTING: Filling area with chosen element";
901  bool FillSelectionFlag = false;
903  {
904  UnicodeString MessageStr = "Click 'Yes' to fill the area with the chosen element or 'No' to abort.\n"
905  "Existing elements won't be overwritten although track can\n"
906  "have platforms and non-station named location elements added.\n\nThis message will not be shown again.";
907  int button = Application->MessageBox(MessageStr.c_str(), L"", MB_YESNO);
908  if(button == IDYES)
909  {
910  FillSelectionFlag = true;
911  }
912  }
913  if(FillSelectionFlag || FillSelectionMessageSentFlag)
914  {
915  bool TrackLinkingRequiredFlag = true;
916  for(int HLoc = SelectRect.left; HLoc < SelectRect.right; HLoc++)
917  {
918  for(int VLoc = SelectRect.top; VLoc < SelectRect.bottom; VLoc++)
919  {
920  if((HLoc != SelectRect.right) || (VLoc != SelectRect.bottom))
921  {
922  Track->PlotAndAddTrackElement(3, CurrentSpeedButton->Tag, 0, HLoc, VLoc, TrackLinkingRequiredFlag, false); //false for internal checks
923  // above now has extra zero 'Aspect' parameter at v2.2.0 so can distinguish between adding track and pasting
924  }
925  else
926  {
927  Track->PlotAndAddTrackElement(4, CurrentSpeedButton->Tag, 0, HLoc, VLoc, TrackLinkingRequiredFlag, true); //internal checks true for last plot
928  }
929  }
930  }
931  }
932  Track->SetTrackFinished(false);
933  ClearandRebuildRailway(80); // to remove selection outline
934  SelectionValid = false;
935  Track->CopyFlag = false;
937  ResetSelectRect();
938  SetLevel1Mode(139);
940  SetLevel2TrackMode(66);
942  Screen->Cursor = TCursor(-2); // Arrow
943  ReselectMenuItem->Enabled = true; //allow when filling areas
944  }
945  }
946  }
947  else
948  {
949  CurrentSpeedButton = 0;
950  }
951  Utilities->CallLogPop(1163);
952  }
953  catch(const Exception &e)
954  {
955  ErrorLog(122, e.Message);
956  }
957 }
958 
959 // ---------------------------------------------------------------------------
960 void __fastcall TInterface::TrackOKButtonClick(TObject *Sender)
961 {
962  try
963  {
964  TrainController->LogEvent("TrackOKButtonClick");
965  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrackOKButtonClick");
966  SelectionValid = false;
968  bool LocError;
969  int HLoc, VLoc;
970  // erase any corrupted PrefDirs then rebuild track & PrefDir vectors
971 // EveryPrefDir->EraseCorruptedElementsAfterTrackBuild(); not needed after dispensed with blank track elements for erased elements
972  if(!(Track->TryToConnectTrack(0, LocError, HLoc, VLoc, true))) // true for give messages
973  // if successful repositions TrackVector & builds TrackMap
974  {
975  if(LocError) // links not complete or other error - show offending element
976  {
977  while((Display->DisplayOffsetH - HLoc) > 0)
978  Display->DisplayOffsetH -= (Utilities->ScreenElementWidth / 2); // use 30 instead of 60 so less likely to appear behind the message box
979  while((HLoc - Display->DisplayOffsetH) > (Utilities->ScreenElementWidth - 1))
981  while((Display->DisplayOffsetV - VLoc) > 0)
982  Display->DisplayOffsetV -= (Utilities->ScreenElementHeight / 2); // use 18 instead of 36 so less likely to appear behind the message box
983  while((VLoc - Display->DisplayOffsetV) > (Utilities->ScreenElementHeight - 1))
986  Display->InvertElement(0, HLoc * 16, VLoc * 16);
987  ShowMessage("Incomplete track or other error - see inverted element (may be behind this message)");
988  ClearandRebuildRailway(1); // to clear inversion
990  SetLevel1Mode(39);
991  Level2TrackMode = AddTrack; // go to add track regardless of where started from
993  Utilities->CallLogPop(0);
994  return;
995  }
996  else
997  { // reach here if there are no track elements
998  ShowMessage("Unable to set any track links");
1000  SetLevel1Mode(40);
1002  SetLevel2TrackMode(4); // go to add track regardless of where started from
1003  Utilities->CallLogPop(1);
1004  return;
1005  }
1006  }
1007  else
1008  {
1009  // success ('TrackFinished' set in TryToConnectTrack)
1010  EveryPrefDir->RebuildPrefDirVector(0); // from TrackMap
1011  ShowMessage("Successful Completion");
1012  }
1013 // success if reach here ('TrackFinished' set in TryToConnectTrack)
1014  if(Level2TrackMode == AddTrack)
1015  {
1017  SetLevel1Mode(41);
1018  SetLevel2TrackMode(5);
1019  }
1020  else
1021  {
1023  SetLevel1Mode(36); // back to TrackMode if not in AddTrack mode
1024  }
1025  Utilities->CallLogPop(2);
1026  }
1027  catch(const Exception &e)
1028  {
1029  ErrorLog(3, e.Message);
1030  }
1031 }
1032 
1033 // ---------------------------------------------------------------------------
1034 void __fastcall TInterface::SetGapsButtonClick(TObject *Sender)
1035 {
1036  try
1037  {
1038  TrainController->LogEvent("SetGapsButtonClick");
1039  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SetGapsButtonClick");
1040  SelectionValid = false;
1041  ReselectMenuItem->Enabled = false;
1043  SetLevel1Mode(42);
1045  SetLevel2TrackMode(6);
1046  Utilities->CallLogPop(1164);
1047  }
1048  catch(const Exception &e)
1049  {
1050  ErrorLog(123, e.Message);
1051  }
1052 }
1053 
1054 // ---------------------------------------------------------------------------
1055 void __fastcall TInterface::AddTextButtonClick(TObject *Sender)
1056 {
1057  try
1058  {
1059  TrainController->LogEvent("AddTextButtonClick");
1060  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddTextButtonClick");
1062  SetLevel1Mode(43);
1064  SetLevel2TrackMode(7);
1065  Utilities->CallLogPop(1165);
1066  }
1067  catch(const Exception &e)
1068  {
1069  ErrorLog(124, e.Message);
1070  }
1071 }
1072 
1073 // ---------------------------------------------------------------------------
1074 void __fastcall TInterface::MoveTextOrGraphicButtonClick(TObject *Sender)
1075 {
1076  try
1077  {
1078  TrainController->LogEvent("MoveTextOrGraphicButtonClick");
1079  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveTextOrGraphicButtonClick");
1081  SetLevel1Mode(44);
1083  SetLevel2TrackMode(8);
1084  Utilities->CallLogPop(1166);
1085  }
1086  catch(const Exception &e)
1087  {
1088  ErrorLog(125, e.Message);
1089  }
1090 }
1091 
1092 // ---------------------------------------------------------------------------
1093 void __fastcall TInterface::TextBoxKeyPress(TObject *Sender, char &Key)
1094 {
1095  try
1096  {
1097  TrainController->LogEvent("TextBoxKeyPress," + AnsiString(Key));
1098  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TextBoxKeyPress," + AnsiString(Key));
1099  if(Key == '\x0D') // CR
1100  {
1101  if(TextBox->Text != "") // if blank then don't save
1102  {
1103  if(Display->GetFont()->Color == clB5G5R5) // white
1104  {
1105  TFont *TempFont = new TFont;
1106  TempFont->Assign(Display->GetFont());
1107  TempFont->Color = clB0G0R0; // change to black for vector & saving
1108  Display->SetFont(TempFont);
1109  delete TempFont;
1110  }
1111  TFont *DisplayFont = Display->GetFont();
1112  TTextItem TempText = TTextItem(Text_X, Text_Y, TextBox->Text, DisplayFont);
1113  TempText.Font = DisplayFont; // may have been changed in above constructor when returned as reference
1115  }
1116  EditMenu->Enabled = true;
1117  TextBox->Visible = false;
1118  SetLevel2TrackMode(56); // to enable 'move text' if first text item added
1119  }
1120  else if(Key == '\x1B') // escape
1121  {
1122  TextBox->Visible = false;
1123  }
1124  Utilities->CallLogPop(3);
1125  }
1126  catch(const Exception &e)
1127  {
1128  ErrorLog(4, e.Message);
1129  }
1130 }
1131 
1132 // ---------------------------------------------------------------------------
1133 void __fastcall TInterface::LocationNameButtonClick(TObject *Sender)
1134 {
1135  try
1136  {
1137  TrainController->LogEvent("LocationNameButtonClick");
1138  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameButtonClick");
1140  SetLevel1Mode(45);
1142  SetLevel2TrackMode(9);
1143  Utilities->CallLogPop(1167);
1144  }
1145  catch(const Exception &e)
1146  {
1147  ErrorLog(126, e.Message);
1148  }
1149 }
1150 
1151 // ---------------------------------------------------------------------------
1152 void __fastcall TInterface::LocationNameKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
1153 {
1154  try
1155  {
1156  TrainController->LogEvent("LocationNameKeyUp," + AnsiString(Key));
1157  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameKeyUp," + AnsiString(Key));
1158  if(Track->LNPendingList.empty())
1159  {
1160  ShowMessage("Error, location name being entered without an entry in LNPendingList");
1162  SetLevel1Mode(46);
1164  SetLevel2TrackMode(10);
1165  Utilities->CallLogPop(4);
1166  return;
1167  }
1168  if(Key == '\x1B') // escape
1169  {
1170  Track->LNPendingList.clear(); // get rid of existing entry
1172  SetLevel1Mode(47);
1174  SetLevel2TrackMode(11);
1175  Utilities->CallLogPop(5);
1176  return;
1177  }
1178  if(Key == '\x0D')
1179  {
1180  Screen->Cursor = TCursor(-11); // Hourglass;
1182  AnsiString ExistingName;
1183  if(Track->LNPendingList.front() > -1)
1184  ExistingName = Track->InactiveTrackElementAt(27, Track->LNPendingList.front()).LocationName;
1185  else
1186  ExistingName = Track->TrackElementAt(425, -1 - (Track->LNPendingList.front())).LocationName;
1187  if(Track->LocationNameAllocated(1, LocationNameTextBox->Text) && (ExistingName != LocationNameTextBox->Text))
1188  { // name allocated to a different location
1189  UnicodeString MessageStr = UnicodeString("Another location named '") + LocationNameTextBox->Text +
1190  UnicodeString("' already exists. If you continue its name will be erased. Do you wish to continue?");
1191  int button = Application->MessageBox(MessageStr.c_str(), L"Warning!", MB_YESNO | MB_ICONWARNING);
1192  if(button == IDNO)
1193  {
1194  Track->LNPendingList.clear(); // get rid of existing entry
1195  Screen->Cursor = TCursor(-2); // Arrow
1197  SetLevel1Mode(48);
1199  SetLevel2TrackMode(12);
1200  Utilities->CallLogPop(6);
1201  return;
1202  }
1204  Track->EnterLocationName(1, LocationNameTextBox->Text, false);
1205  int HPos, VPos;
1206  bool UseExistingPosition = false;
1207  if(EraseLocationNameText(0, LocationNameTextBox->Text, HPos, VPos))
1208  {;
1209  } // condition not used
1210  // above may be redundant at v1.1.0 due to name erase in EnterLocationName
1211  // but, the location to be named may also have an existing name, in which case that needs to be erased
1212  // and the position re-used
1213  if(ExistingName != "")
1214  {
1215  if(EraseLocationNameText(3, ExistingName, HPos, VPos))
1216  UseExistingPosition = true; // may be redundant at v1.1.0 due to name erase in EnterLocationName
1217  }
1218  AddLocationNameText(0, LocationNameTextBox->Text, HPos, VPos, UseExistingPosition);
1219  Screen->Cursor = TCursor(-2); // Arrow
1221  SetLevel1Mode(49);
1223  SetLevel2TrackMode(13);
1224  Utilities->CallLogPop(7);
1225  return;
1226  }
1227  else if(Track->LocationNameAllocated(2, LocationNameTextBox->Text) && (ExistingName == LocationNameTextBox->Text))
1228  { // same name being entered again
1229  Track->LNPendingList.clear(); // get rid of existing entry as the location already has this name
1230  // but in case the name is not already in text vector erase it and re-add it
1231  // if it wasn't in the vector erasing it has no effect
1232  int HPos, VPos;
1233  bool UseExistingPosition = false;
1234  if(EraseLocationNameText(2, LocationNameTextBox->Text, HPos, VPos))
1235  UseExistingPosition = true;
1236  // above may be redundant at v1.1.0 due to name erase in EnterLocationName
1237  AddLocationNameText(2, LocationNameTextBox->Text, HPos, VPos, UseExistingPosition);
1238  Screen->Cursor = TCursor(-2); // Arrow
1240  SetLevel1Mode(50);
1242  SetLevel2TrackMode(14);
1243  Utilities->CallLogPop(8);
1244  return;
1245  }
1246  else
1247  { // either a new name for an unnamed location, or a different name for a named location
1248  // check validity of entry
1249  AnsiString LocStr = LocationNameTextBox->Text;
1250  LocStr = LocStr.Trim(); // strip leading & trailing spaces, and control characters
1251  LocationNameTextBox->Text = LocStr; // reset this as used below
1252 /* drop this, now covered by ...Trim() above
1253  //strip leading spaces
1254  while((LocStr != "") && (LocStr[1] == ' '))
1255  {
1256  LocStr = LocStr.SubString(2, LocStr.Length()-1);
1257  }
1258 */
1259  if((LocStr != "") && (LocStr[1] >= '0') && (LocStr[1] <= '9')) // can't begin with a number
1260  {
1261  Screen->Cursor = TCursor(-2); // Arrow
1262  ShowMessage("Location name can't begin with a number");
1264  SetLevel1Mode(51);
1266  SetLevel2TrackMode(15);
1267  Utilities->CallLogPop(776);
1268  return;
1269  }
1270  if(LocStr.Length() > 50)
1271  {
1272  Screen->Cursor = TCursor(-2); // Arrow
1273  ShowMessage("Location name too long, 50 characters maximum");
1275  SetLevel1Mode(122);
1277  SetLevel2TrackMode(55);
1278  Utilities->CallLogPop(1735);
1279  return;
1280  }
1281  for(int x = 1; x <= LocStr.Length(); x++)
1282  {
1283  char Ch = LocStr[x];
1284  if((Ch != ' ') && (Ch != '&') && (Ch != '(') && (Ch != ')') && (Ch != ':') && (Ch != 39) && (Ch != '.') && (Ch != '-') && (Ch != '+') &&
1285  (Ch != '/') && ((Ch < '0') || (Ch > '9')) && ((Ch < 'A') || (Ch > 'Z')) && ((Ch < 'a') || (Ch > 'z')))
1286  {
1287  Screen->Cursor = TCursor(-2); // Arrow
1288  ShowMessage(
1289  "Location name contains one or more invalid characters, must be alphanumeric, brackets, space, full stop, colon, inverted comma, '-', '+', '/' or '&&'");
1291  SetLevel1Mode(52);
1293  SetLevel2TrackMode(16);
1294  Utilities->CallLogPop(777);
1295  return;
1296  }
1297  }
1298  if(LocStr == "cdt") // this has Time:Command which could be confused with Time:Loc
1299  {
1300  Screen->Cursor = TCursor(-2); // Arrow
1301  ShowMessage("Location name cannot be 'cdt', this name would interfere with the timetable");
1303  SetLevel1Mode(53);
1305  SetLevel2TrackMode(17);
1306  Utilities->CallLogPop(778);
1307  return;
1308  }
1309  Track->EnterLocationName(2, LocStr, false);
1310  // need to check if the location already has a name, and if so erase it from the textvector
1311  int HPos, VPos;
1312  bool UseExistingPosition = false;
1313  if(ExistingName != "")
1314  {
1315  if(EraseLocationNameText(1, ExistingName, HPos, VPos))
1316  UseExistingPosition = true; // may be redundant at v1.1.0 due to name erase in EnterLocationName
1317  }
1318  AddLocationNameText(1, LocationNameTextBox->Text, HPos, VPos, UseExistingPosition);
1319  Screen->Cursor = TCursor(-2); // Arrow
1321  SetLevel1Mode(54);
1323  SetLevel2TrackMode(18);
1324  Utilities->CallLogPop(9);
1325  return;
1326  }
1327  }
1328  Screen->Cursor = TCursor(-2); // Arrow
1329  Utilities->CallLogPop(10);
1330  }
1331  catch(const Exception &e)
1332  {
1333  ErrorLog(5, e.Message);
1334  }
1335 }
1336 
1337 // ---------------------------------------------------------------------------
1338 void __fastcall TInterface::SetLengthsButtonClick(TObject *Sender)
1339 {
1340  try
1341  {
1342  TrainController->LogEvent("SetLengthsButtonClick");
1343  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SetLengthsButtonClick");
1344  SelectLengthsFlag = false;
1345  ConstructPrefDir->ExternalClearPrefDirAnd4MultiMap(); // added for extended distances
1347  SetLevel1Mode(55);
1349  SetLevel2TrackMode(19);
1350  Utilities->CallLogPop(1168);
1351  }
1352  catch(const Exception &e)
1353  {
1354  ErrorLog(127, e.Message);
1355  }
1356 }
1357 
1358 // ---------------------------------------------------------------------------
1359 void __fastcall TInterface::LengthOKButtonClick(TObject *Sender)
1360 {
1361  try
1362  {
1363  TrainController->LogEvent("LengthOKButtonClick," + DistanceBox->Text + "," + SpeedLimitBox->Text);
1364  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LengthOKButtonClick");
1365  int Dist = 0, SpeedLimit = 0;
1366  AnsiString DistanceStr = DistanceBox->Text;
1367  if(SelectLengthsFlag && (DistanceStr == ""))
1368  DistanceStr = "No change";
1369  AnsiString SpeedStr = SpeedLimitBox->Text;
1370  if(SelectLengthsFlag && (SpeedStr == ""))
1371  SpeedStr = "No change";
1372  if(SelectLengthsFlag)
1373  {
1374  if(DistanceStr == "No change")
1375  Dist = -1; // i.e.don't change
1376  if(SpeedStr == "No change")
1377  SpeedLimit = -1; // i.e.don't change
1378  }
1379  else
1380  {
1381  if(DistanceStr == AnsiString(OverallDistance))
1382  Dist = -1; // i.e.don't change
1383  if((SpeedStr == "Mixed") || (SpeedStr == AnsiString(OverallSpeedLimit)))
1384  SpeedLimit = -1; // i.e.don't change
1385  }
1386  if(((Dist != -1) && (DistanceStr.Length() > 6)) || ((SpeedLimit != -1) && (SpeedStr.Length() > 6)))
1387  {
1388  ShowMessage("One or more entries too long");
1389  Utilities->CallLogPop(11);
1390  return;
1391  }
1392  if((DistanceStr == "") || (SpeedStr == ""))
1393  {
1394  ShowMessage("One or more entries blank");
1395  Utilities->CallLogPop(12);
1396  return;
1397  }
1398  if(SelectLengthsFlag && (Dist != -1))
1399  {
1400  for(int x = 1; x <= DistanceStr.Length(); x++)
1401  {
1402  if((DistanceStr[x] < '0') || (DistanceStr[x] > '9'))
1403  {
1404  ShowMessage("Track length value must be a positive whole number, or blank for no change");
1405  Utilities->CallLogPop(1415);
1406  return;
1407  }
1408  }
1409  }
1410  if(!SelectLengthsFlag)
1411  {
1412  for(int x = 1; x <= DistanceStr.Length(); x++)
1413  {
1414  if((DistanceStr[x] < '0') || (DistanceStr[x] > '9'))
1415  {
1416  ShowMessage("Distance must be a positive whole number");
1417  Utilities->CallLogPop(13);
1418  return;
1419  }
1420  }
1421  }
1422  if(SelectLengthsFlag && (SpeedLimit != -1))
1423  {
1424  for(int x = 1; x <= SpeedStr.Length(); x++)
1425  {
1426  if((SpeedStr[x] < '0') || (SpeedStr[x] > '9'))
1427  {
1428  ShowMessage("Speed limit must be a positive whole number, or blank for no change");
1429  Utilities->CallLogPop(1416);
1430  return;
1431  }
1432  }
1433  }
1434  if(!SelectLengthsFlag && (SpeedStr != "Mixed"))
1435  {
1436  for(int x = 1; x <= SpeedStr.Length(); x++)
1437  {
1438  if((SpeedStr[x] < '0') || (SpeedStr[x] > '9'))
1439  {
1440  ShowMessage("Speed limit must be a positive whole number, or 'Mixed'");
1441  Utilities->CallLogPop(14);
1442  return;
1443  }
1444  }
1445  }
1446  if(Dist != -1)
1447  Dist = DistanceStr.ToInt();
1448  if(SpeedLimit != -1)
1449  SpeedLimit = SpeedStr.ToInt();
1450 /* don't need this with new condition below
1451  if(SelectLengthsFlag && (Dist != -1) && (Dist < 20))
1452  {
1453  ShowMessage("Track length value must be a minimum of 20m, setting to 20m");
1454  Dist = 20;
1455  }
1456 */
1457  if(((Dist != -1) && (Dist < 20)) || ((SpeedLimit != -1) && (SpeedLimit < 10)) || ((SpeedLimit != -1) && (SpeedLimit > TTrain::MaximumSpeedLimit)))
1458  // new limiting values for v0.6 (used only to fail at either value 0); added TTrain::MaxSpeedLimit at v2.1.0
1459  {
1460  ShowMessage("Lengths must be 20m or more, and speeds must be between 10km/h and 400km/h"); // changed at v2.1.0 to limit max speed
1461  Utilities->CallLogPop(15);
1462  return;
1463  }
1464  DistanceBox->Text = "";
1465  SpeedLimitBox->Text = "";
1466  if(SelectLengthsFlag)
1467  {
1468  int LowSelectHLoc = SelectBitmapHLoc;
1469  int HighSelectHLoc = SelectBitmapHLoc + (SelectBitmap->Width / 16);
1470  int LowSelectVLoc = SelectBitmapVLoc;
1471  int HighSelectVLoc = SelectBitmapVLoc + (SelectBitmap->Height / 16);
1472  bool FoundFlag;
1473  bool NamedLocPresent = false;
1474  if((Dist != -1) && (Dist != DefaultTrackLength))
1475  {
1476  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1477  {
1478  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1479  {
1481  NamedLocPresent = true;
1482  }
1483  }
1484  }
1485  if(NamedLocPresent && (Dist < 50)) // changed in v2.4.0
1486  {
1487  ShowMessage("Note: Named location elements are quite short. If they are too short the simulation might depart too far from reality.");
1488  }
1489 
1490  if(NamedLocPresent && (Dist > 200)) // changed in v2.4.0
1491  {
1492  ShowMessage("Note: Named location elements are quite long. If they are too long the simulation might depart too far from reality.");
1493  }
1494 
1495  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1496  {
1497  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1498  {
1499  int VecPos = Track->GetVectorPositionFromTrackMap(34, x, y, FoundFlag);
1500  if(FoundFlag)
1501  {
1502  if(Dist > -1) // && !(Track->IsPlatformOrNamedNonStationLocationPresent(7, x, y)))
1503  {
1504  Track->TrackElementAt(692, VecPos).Length01 = Dist;
1505  if(Track->TrackElementAt(693, VecPos).Length23 != -1)
1506  {
1507  Track->TrackElementAt(694, VecPos).Length23 = Dist;
1508  }
1509  }
1510  if(SpeedLimit > -1)
1511  {
1512  Track->TrackElementAt(695, VecPos).SpeedLimit01 = SpeedLimit;
1513  if(Track->TrackElementAt(696, VecPos).SpeedLimit23 != -1)
1514  {
1515  Track->TrackElementAt(697, VecPos).SpeedLimit23 = SpeedLimit;
1516  }
1517  }
1518  }
1519  }
1520  }
1521  TrackLengthPanel->Visible = false;
1522  SelectLengthsFlag = false; // go back to normal distance setting mode
1523  }
1524  else
1525  {
1526  SetTrackLengths(1, Dist, SpeedLimit);
1527  }
1529  SetLevel1Mode(57);
1531  SetLevel2TrackMode(21);
1532  Utilities->CallLogPop(16);
1533  }
1534  catch(const Exception &e)
1535  {
1536  ErrorLog(6, e.Message);
1537  }
1538 }
1539 
1540 // ---------------------------------------------------------------------------
1541 void __fastcall TInterface::LengthCancelButtonClick(TObject *Sender)
1542 {
1543  try
1544  {
1545  TrainController->LogEvent("LengthCancelButtonClick");
1546  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LengthCancelButtonClick");
1547  DistanceBox->Text = "";
1548  SpeedLimitBox->Text = "";
1549  TrackLengthPanel->Visible = false;
1550  SelectLengthsFlag = false; // go back to normal distance setting mode
1552  SetLevel1Mode(59);
1554  SetLevel2TrackMode(23);
1555  Utilities->CallLogPop(1169);
1556  }
1557  catch(const Exception &e)
1558  {
1559  ErrorLog(128, e.Message);
1560  }
1561 }
1562 
1563 // ---------------------------------------------------------------------------
1564 void __fastcall TInterface::ResetDefaultLengthButtonClick(TObject *Sender)
1565 {
1566  try
1567  {
1568  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ResetDefaultLengthButtonClick");
1569  TMsgDlgButtons Buttons;
1570  Buttons << mbYes << mbNo;
1571  if(MessageDlg("This will reset the selected elements to default lengths & speed limits. Proceed?", mtWarning, Buttons, 0) == mrNo)
1572  {
1573  // leave all as was before
1574  Utilities->CallLogPop(17);
1575  return;
1576  }
1577  else
1578  {
1579  TrainController->LogEvent("Accepted ResetDefaultLengthButtonClick");
1580  DistanceBox->Text = "";
1581  SpeedLimitBox->Text = "";
1582  if(SelectLengthsFlag)
1583  {
1584  int LowSelectHLoc = SelectBitmapHLoc;
1585  int HighSelectHLoc = SelectBitmapHLoc + (SelectBitmap->Width / 16);
1586  int LowSelectVLoc = SelectBitmapVLoc;
1587  int HighSelectVLoc = SelectBitmapVLoc + (SelectBitmap->Height / 16);
1588  bool FoundFlag;
1589  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1590  {
1591  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1592  {
1593  int VecPos = Track->GetVectorPositionFromTrackMap(35, x, y, FoundFlag);
1594  if(FoundFlag)
1595  {
1597  if(Track->TrackElementAt(699, VecPos).Length23 != -1)
1598  {
1600  }
1602  if(Track->TrackElementAt(702, VecPos).SpeedLimit23 != -1)
1603  {
1605  }
1606  }
1607  }
1608  }
1609  TrackLengthPanel->Visible = false;
1610 // ClearandRebuildRailway(47); don't need this
1611  SelectLengthsFlag = false; // go back to normal distance setting mode
1612  }
1613  else
1614  {
1615  TrackLengthPanel->Visible = false;
1616  bool FoundFlag;
1617  if(ConstructPrefDir->PrefDirSize() == 0)
1618  {
1619  Utilities->CallLogPop(1120);
1620  return;
1621  }
1622  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
1623  {
1624  TPrefDirElement PrefDirElement = ConstructPrefDir->GetFixedPrefDirElementAt(169, x);
1625  TTrackElement & TrackElement = Track->TrackElementAt(37, Track->GetVectorPositionFromTrackMap(40, PrefDirElement.HLoc, PrefDirElement.VLoc,
1626  FoundFlag));
1627  if((TrackElement.TrackType == Points) || (TrackElement.TrackType == Crossover) || (TrackElement.TrackType == Bridge))
1628  // only set the relevant track to default length & speed limit
1629  {
1630  if((PrefDirElement.GetELinkPos() < 2) && (PrefDirElement.GetXLinkPos() < 2)) // could be one of each for points
1631  {
1632  TrackElement.Length01 = DefaultTrackLength;
1633  TrackElement.SpeedLimit01 = DefaultTrackSpeedLimit; // 200km/h = 125mph
1634  }
1635  else
1636  {
1637  TrackElement.Length23 = DefaultTrackLength;
1638  TrackElement.SpeedLimit23 = DefaultTrackSpeedLimit; // 200km/h = 125mph
1639  }
1640  }
1641  else // any other 1 track element, including platforms being present
1642  {
1643  if((PrefDirElement.GetELinkPos() > 1) && (PrefDirElement.GetXLinkPos() > 1))
1644  {
1645  throw Exception("Error, XLinkPos > 1 in SetOneDefaultTrackLength at " + AnsiString(TrackElement.HLoc) + " & " +
1646  AnsiString(TrackElement.VLoc));
1647  }
1648  TrackElement.Length01 = DefaultTrackLength;
1649  TrackElement.SpeedLimit01 = DefaultTrackSpeedLimit; // 200km/h = 125mph
1650  TrackElement.Length23 = -1;
1651  TrackElement.SpeedLimit23 = -1;
1652  }
1653  }
1654  }
1656  SetLevel1Mode(61);
1658  SetLevel2TrackMode(25);
1659  }
1660  Utilities->CallLogPop(18);
1661  }
1662  catch(const Exception &e)
1663  {
1664  ErrorLog(7, e.Message);
1665  }
1666 }
1667 
1668 // ---------------------------------------------------------------------------
1669 void __fastcall TInterface::RestoreAllDefaultLengthsButtonClick(TObject *Sender)
1670 {
1671  try
1672  {
1673  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RestoreAllDefaultLengthsButtonClick");
1674  TMsgDlgButtons Buttons;
1675  Buttons << mbYes << mbNo;
1676  if(MessageDlg("This will reset ALL track elements to default lengths & speed limits. Proceed?", mtWarning, Buttons, 0) == mrNo)
1677  {
1678  // leave all as was before
1679  Utilities->CallLogPop(19);
1680  return;
1681  }
1682  else
1683  {
1685  }
1686  TrainController->LogEvent("Accepted RestoreAllDefaultLengthsButtonClick");
1687  DistanceBox->Text = "";
1688  SpeedLimitBox->Text = "";
1689  TrackLengthPanel->Visible = false;
1690  SelectLengthsFlag = false; // go back to normal distance setting mode
1692  SetLevel1Mode(63);
1694  SetLevel2TrackMode(27);
1695  Utilities->CallLogPop(20);
1696  }
1697  catch(const Exception &e)
1698  {
1699  ErrorLog(8, e.Message);
1700  }
1701 }
1702 
1703 // ---------------------------------------------------------------------------
1704 void __fastcall TInterface::ExitTrackButtonClick(TObject *Sender)
1705 {
1706  try
1707  {
1708  TrainController->LogEvent("ExitTrackButtonClick");
1709  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitTrackButtonClick");
1710  if(Level2TrackMode == CutMoving)
1711  {
1712  Level2TrackMode = Pasting; // to paste the selection
1713  SetLevel2TrackMode(53);
1714  }
1715  DevelopmentPanel->Visible = false; // development use only
1716  ScreenGridFlag = false;
1717  SelectionValid = false;
1718  Track->SelectGraphicVector.clear();
1719  // delete all unwanted TPictures in UserGraphicMap
1720  if(!Track->UserGraphicMap.empty()) // if empty skip it
1721  {
1722  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.begin();
1723  do
1724  {
1725  bool GraphicFoundInVector = false;
1726  for(TTrack::TUserGraphicVector::iterator UGVIt = Track->UserGraphicVector.begin(); UGVIt < Track->UserGraphicVector.end(); UGVIt++)
1727  {
1728  if(UGMIt->first == UGVIt->FileName)
1729  {
1730  GraphicFoundInVector = true;
1731  break;
1732  }
1733  }
1734  if(!GraphicFoundInVector)
1735  {
1736  delete UGMIt->second;
1737  Track->UserGraphicMap.erase(UGMIt);
1738  UGMIt = Track->UserGraphicMap.begin(); // reset the iterator because erasing an element it points to invalidates it & if use it after then
1739  // behaviour is undefined, the iteration will end eventually because the map has got shorter after an erase
1740  }
1741  else
1742  {
1743  UGMIt++;
1744  }
1745  }
1746  while(UGMIt != Track->UserGraphicMap.end());
1747  }
1748  Level1Mode = BaseMode;
1749  SetLevel1Mode(2);
1750  Utilities->CallLogPop(1170);
1751  }
1752  catch(const Exception &e)
1753  {
1754  ErrorLog(129, e.Message);
1755  }
1756 }
1757 
1758 // ---------------------------------------------------------------------------
1759 void __fastcall TInterface::TextOrUserGraphicGridButtonClick(TObject *Sender)
1760 {
1761  try
1762  {
1763  TrainController->LogEvent("TextOrUserGraphicGridButtonClick," + AnsiString(TextOrUserGraphicGridVal));
1764  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TextOrUserGraphicGridButtonClick");
1765  if(TextOrUserGraphicGridVal == 1)
1766  {
1768  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision2");
1769  }
1770  else if(TextOrUserGraphicGridVal == 2)
1771  {
1773  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision4");
1774  }
1775  else if(TextOrUserGraphicGridVal == 4)
1776  {
1778  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision8");
1779  }
1780  else if(TextOrUserGraphicGridVal == 8)
1781  {
1783  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision16");
1784  }
1785  else
1786  {
1788  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision1");
1789  }
1790  Utilities->CallLogPop(1171);
1791  }
1792  catch(const Exception &e)
1793  {
1794  ErrorLog(130, e.Message);
1795  }
1796 }
1797 
1798 // ---------------------------------------------------------------------------
1799 void __fastcall TInterface::SigAspectButtonClick(TObject *Sender)
1800 {
1801  try
1802  {
1803  TrainController->LogEvent("SigAspectButtonClick," + AnsiString(Track->SignalAspectBuildMode));
1804  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SigAspectButtonClick");
1806  {
1808  SigAspectButton->Glyph->LoadFromResourceName(0, "ThreeAspect");
1809  }
1811  {
1813  SigAspectButton->Glyph->LoadFromResourceName(0, "TwoAspect");
1814  }
1816  {
1818  SigAspectButton->Glyph->LoadFromResourceName(0, "GroundSig");
1819 // set all signal glyphs to ground signals
1821  }
1822  else
1823  {
1825  SigAspectButton->Glyph->LoadFromResourceName(0, "FourAspect");
1826 // set all signal glyphs to normal signals
1828  }
1829  Utilities->CallLogPop(1869);
1830  }
1831  catch(const Exception &e)
1832  {
1833  ErrorLog(180, e.Message);
1834  }
1835 }
1836 
1837 // ---------------------------------------------------------------------------
1838 void __fastcall TInterface::FontButtonClick(TObject *Sender)
1839 {
1840  try
1841  {
1842  TrainController->LogEvent("FontButtonClick");
1843  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",FontButtonClick");
1844  FontDialog->Font = Display->GetFont(); //sets the dialog box font to the currently used font
1845  FontDialog->Execute(); //this displays the dialog box
1846  if(FontDialog->Font->Color == clB5G5R5) //white
1847  FontDialog->Font->Color = clB0G0R0; //black - don't store white in font, will display black as white on dark backgrounds
1848  Display->SetFont(FontDialog->Font); //sets the displayed font to the output from the dialog box
1849  if(TextBox->Visible)
1850  TextBox->SetFocus();
1851  else if(LocationNameTextBox->Visible)
1852  LocationNameTextBox->SetFocus();
1853  Utilities->CallLogPop(1172);
1854  }
1855  catch(const Exception &e)
1856  {
1857  ErrorLog(131, e.Message);
1858  }
1859 }
1860 
1861 // ---------------------------------------------------------------------------
1862 
1863 void __fastcall TInterface::ScreenGridButtonClick(TObject *Sender)
1864 {
1865  try
1866  {
1867  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenGridButtonClick");
1868  if(ScreenGridFlag)
1869  {
1870  TrainController->LogEvent("ScreenGridButtonClick + ScreenGrid off");
1871  ScreenGridFlag = false;
1872  }
1873  else
1874  {
1875  TrainController->LogEvent("ScreenGridButtonClick + ScreenGrid on");
1876  ScreenGridFlag = true;
1877  }
1879  Utilities->CallLogPop(89);
1880  }
1881  catch(const Exception &e)
1882  {
1883  ErrorLog(33, e.Message);
1884  }
1885 }
1886 
1887 // ---------------------------------------------------------------------------
1888 // PrefDir Interface
1889 // ---------------------------------------------------------------------------
1890 void __fastcall TInterface::PlanPrefDirsMenuItemClick(TObject *Sender) // Mode Menu Item
1891 {
1892  try
1893  {
1894  TrainController->LogEvent("PlanPrefDirsMenuItemClick");
1895  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PlanPrefDirsMenuItemClick");
1897  SetLevel1Mode(3);
1898  Utilities->CallLogPop(1173);
1899  }
1900  catch(const Exception &e)
1901  {
1902  ErrorLog(132, e.Message);
1903  }
1904 }
1905 
1906 // ---------------------------------------------------------------------------
1907 void __fastcall TInterface::AddPrefDirButtonClick(TObject *Sender)
1908 {
1909  try
1910  {
1911  TrainController->LogEvent("AddPrefDirButtonClick");
1912  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddPrefDirButtonClick");
1913  if(ConstructPrefDir->PrefDirSize() == 0)
1914  {
1915  ShowMessage("No preferred direction selection");
1916  Utilities->CallLogPop(22);
1917  return;
1918  }
1919  Screen->Cursor = TCursor(-11); // Hourglass;
1923  SetLevel1Mode(4);
1924  Screen->Cursor = TCursor(-2); // Arrow
1925  Utilities->CallLogPop(23);
1926  }
1927  catch(const Exception &e)
1928  {
1929  ErrorLog(10, e.Message);
1930  }
1931 }
1932 
1933 // ---------------------------------------------------------------------------
1934 void __fastcall TInterface::DeleteAllPrefDirButtonClick(TObject *Sender)
1935 {
1936  try
1937  {
1938  TrainController->LogEvent("DeleteAllPrefDirButtonClick");
1939  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteAllPrefDirButtonClick");
1940  TMsgDlgButtons Buttons;
1941  Buttons << mbYes << mbNo;
1942  if(MessageDlg("Do you really want to clear all preferred directions?", mtWarning, Buttons, 0) == mrNo)
1943  {
1944  Utilities->CallLogPop(24);
1945  return;
1946  }
1947  // leave all as was before pressed DeleteAllPrefDirButton
1948  else
1949  {
1954  SetLevel1Mode(5);
1955  }
1956  Utilities->CallLogPop(25);
1957  }
1958  catch(const Exception &e)
1959  {
1960  ErrorLog(11, e.Message);
1961  }
1962 }
1963 // ---------------------------------------------------------------------------
1964 
1965 void __fastcall TInterface::DeleteOnePrefDirButtonClick(TObject *Sender)
1966 {
1967  try
1968  {
1969  TrainController->LogEvent("DeleteOnePrefDirButtonClick");
1970  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteOnePrefDirButtonClick");
1971  ResetChangedFileDataAndCaption(18, false);
1972 // RlyFile = false; - don't alter this just for PrefDir changes
1973  Screen->Cursor = TCursor(-11); // Hourglass;
1974  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
1975  {
1978  }
1981  SetLevel1Mode(81); // all PrefDir truncated
1982  Screen->Cursor = TCursor(-2); // Arrow
1983  Utilities->CallLogPop(1591);
1984  }
1985  catch(const Exception &e)
1986  {
1987  ErrorLog(46, e.Message);
1988  }
1989 }
1990 
1991 // ---------------------------------------------------------------------------
1992 
1993 void __fastcall TInterface::ExitPrefDirButtonClick(TObject *Sender)
1994 {
1995  try
1996  {
1997  TrainController->LogEvent("ExitPrefDirButtonClick");
1998  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitPrefDirButtonClick");
1999  Level1Mode = BaseMode;
2000  SetLevel1Mode(6);
2001  Utilities->CallLogPop(1554);
2002  }
2003  catch(const Exception &e)
2004  {
2005  ErrorLog(133, e.Message);
2006  }
2007 }
2008 
2009 // ---------------------------------------------------------------------------
2010 // Operate Railway Interface
2011 // ---------------------------------------------------------------------------
2012 void __fastcall TInterface::OperateRailwayMenuItemClick(TObject *Sender) // Mode Menu Item
2013 {
2014  try
2015  {
2016  TrainController->LogEvent("OperateRailwayMenuItemClick");
2017  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperateRailwayMenuItemClick");
2018  TTrain::NextTrainID = 0; // reset to 0 whenever enter operating mode
2019  AllRoutes->NextRouteID = 0; // reset to 0 whenever enter operating mode
2020  Level1Mode = OperMode;
2021  SetLevel1Mode(7);
2022  Utilities->CallLogPop(26);
2023  }
2024  catch(const Exception &e)
2025  {
2026  ErrorLog(12, e.Message);
2027  }
2028 }
2029 
2030 // ---------------------------------------------------------------------------
2031 void __fastcall TInterface::OperateButtonClick(TObject *Sender)
2032 {
2033  try
2034  {
2035  TrainController->LogEvent("StartOperationButtonClick");
2036  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperateButtonClick");
2038  {
2040  SetLevel2OperMode(0);
2041  }
2042  else
2043  {
2045  SetLevel2OperMode(1);
2046  }
2047  Utilities->CallLogPop(1175);
2048  }
2049  catch(const Exception &e)
2050  {
2051  ErrorLog(37, e.Message);
2052  }
2053 }
2054 
2055 // ---------------------------------------------------------------------------
2056 void __fastcall TInterface::AutoSigsButtonClick(TObject *Sender)
2057  // must have PrefDirs to be available
2058 {
2059  try
2060  {
2061  TrainController->LogEvent("AutoSigsButtonClick");
2062  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AutoSigsButtonClick");
2063  AutoSigsFlag = true;
2064  PreferredRoute = true;
2065  ConsecSignalsRoute = true;
2066 
2067  AutoSigsButton->Enabled = false;
2068  SigPrefButton->Enabled = true;
2069  UnrestrictedButton->Enabled = true;
2070 
2071  InfoPanel->Visible = true;
2072  if(Level2OperMode == PreStart)
2073  InfoPanel->Caption = "PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2074  else
2075  InfoPanel->Caption = "OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2076  InfoCaptionStore = InfoPanel->Caption;
2077  AutoRouteStartMarker->PlotOriginal(1, Display); // if overlay not plotted will ignore
2078  SigRouteStartMarker->PlotOriginal(2, Display); // if overlay not plotted will ignore
2079  NonSigRouteStartMarker->PlotOriginal(3, Display); // if overlay not plotted will ignore
2081  Utilities->CallLogPop(28);
2082  }
2083  catch(const Exception &e)
2084  {
2085  ErrorLog(14, e.Message);
2086  }
2087 }
2088 
2089 // ---------------------------------------------------------------------------
2090 void __fastcall TInterface::SigPrefButtonClick(TObject *Sender)
2091  // must have PrefDirs to be available
2092 {
2093  try
2094  {
2095  TrainController->LogEvent("SigPrefButtonClick");
2096  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SigPrefButtonClick");
2097  AutoSigsFlag = false;
2098  PreferredRoute = true;
2099  ConsecSignalsRoute = true;
2100 
2101  AutoSigsButton->Enabled = true;
2102  SigPrefButton->Enabled = false;
2103  UnrestrictedButton->Enabled = true;
2104 
2105  InfoPanel->Visible = true;
2106  if(Level2OperMode == PreStart)
2107  InfoPanel->Caption = "PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
2108  else
2109  InfoPanel->Caption = "OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
2110  InfoCaptionStore = InfoPanel->Caption;
2111  AutoRouteStartMarker->PlotOriginal(4, Display); // if overlay not plotted will ignore
2112  SigRouteStartMarker->PlotOriginal(5, Display); // if overlay not plotted will ignore
2113  NonSigRouteStartMarker->PlotOriginal(6, Display); // if overlay not plotted will ignore
2115  Utilities->CallLogPop(29);
2116  }
2117  catch(const Exception &e)
2118  {
2119  ErrorLog(15, e.Message);
2120  }
2121 }
2122 
2123 // ---------------------------------------------------------------------------
2124 void __fastcall TInterface::UnrestrictedButtonClick(TObject *Sender)
2125 {
2126  try
2127  {
2128  TrainController->LogEvent("NoSigNonPrefButtonClick");
2129  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NoSigNonPrefButtonClick");
2130  AutoSigsFlag = false;
2131  PreferredRoute = false;
2132  ConsecSignalsRoute = false;
2133  if(EveryPrefDir->PrefDirSize() > 0)
2134  {
2135  AutoSigsButton->Enabled = true;
2136  SigPrefButton->Enabled = true;
2137  UnrestrictedButton->Enabled = false;
2138  }
2139  else
2140  {
2141  AutoSigsButton->Enabled = false;
2142  SigPrefButton->Enabled = false;
2143  UnrestrictedButton->Enabled = false;
2144  }
2145  InfoPanel->Visible = true;
2146  if(Level2OperMode == PreStart)
2147  InfoPanel->Caption = "PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
2148  else
2149  InfoPanel->Caption = "OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
2150  InfoCaptionStore = InfoPanel->Caption;
2151  AutoRouteStartMarker->PlotOriginal(7, Display); // if overlay not plotted will ignore
2152  SigRouteStartMarker->PlotOriginal(8, Display); // if overlay not plotted will ignore
2153  NonSigRouteStartMarker->PlotOriginal(9, Display); // if overlay not plotted will ignore
2155  Utilities->CallLogPop(30);
2156  }
2157  catch(const Exception &e)
2158  {
2159  ErrorLog(16, e.Message);
2160  }
2161 }
2162 
2163 // ---------------------------------------------------------------------------
2164 void __fastcall TInterface::RouteCancelButtonClick(TObject *Sender)
2165 {
2166  try
2167  {
2168  TrainController->LogEvent("RouteCancelButtonClick");
2169  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RouteCancelButtonClick");
2170  RouteCancelFlag = true;
2171  InfoPanel->Visible = true;
2172  InfoPanel->Caption = "ROUTE CANCELLING: Right click on truncate element, first element to cancel (anywhere else to skip)";
2173  RouteCancelButton->Enabled = false;
2174  AutoRouteStartMarker->PlotOriginal(32, Display); // if overlay not plotted will ignore
2175  SigRouteStartMarker->PlotOriginal(33, Display); // if overlay not plotted will ignore
2176  NonSigRouteStartMarker->PlotOriginal(34, Display); // if overlay not plotted will ignore
2177  Utilities->CallLogPop(1176);
2178  }
2179  catch(const Exception &e)
2180  {
2181  ErrorLog(35, e.Message);
2182  }
2183 }
2184 
2185 // ---------------------------------------------------------------------------
2186 void __fastcall TInterface::PerformanceLogButtonClick(TObject *Sender)
2187 {
2188  try
2189  {
2190  TrainController->LogEvent("PerformanceLogButtonClick");
2191  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PerformanceLogButtonClick");
2193  {
2194  ShowPerformancePanel = true;
2195  PerformancePanel->Visible = true;
2196  PerformanceLogButton->Glyph->LoadFromResourceName(0, "HideLog");
2197  }
2198  else
2199  {
2200  ShowPerformancePanel = false;
2201  PerformancePanel->Visible = false;
2202  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
2203  }
2204  Utilities->CallLogPop(1177);
2205  }
2206  catch(const Exception &e)
2207  {
2208  ErrorLog(36, e.Message);
2209  }
2210 }
2211 // ---------------------------------------------------------------------------
2212 
2213 void __fastcall TInterface::ExitOperationButtonClick(TObject *Sender)
2214 {
2215  try
2216  {
2217  TrainController->LogEvent("ExitOperationButtonClick");
2218  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitOperationButtonClick");
2220  {
2221  UnicodeString MessageStr = "Please note that the session will be lost if it hasn't been saved. Do you still wish to exit?";
2222  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2224  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
2225  TrainController->BaseTime = TDateTime::CurrentDateTime();
2227  if(button == IDNO)
2228  {
2229  Utilities->CallLogPop(751);
2230  return;
2231  }
2232  }
2233  Track->ResetSignals(1);
2234  Track->ResetPoints(1);
2235  TrainController->SendPerformanceSummary(0, Utilities->PerformanceFile); // must come before trains finished becuase examines the train vectors
2236  Utilities->PerformanceFile.close();
2239  RouteMode = None;
2240  PreferredRoute = true;
2241  ConsecSignalsRoute = true;
2243  ShowPerformancePanel = false;
2244  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
2245  ShowOperatorActionPanel = false; // new at v2.2.0
2246  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel"); // new v2.2.0
2247  PerformanceLogBox->Lines->Clear();
2248  PerformancePanel->Visible = false;
2249  PerformancePanel->Top = MainScreen->Top + MainScreen->Height - PerformancePanel->Height;
2250  PerformancePanel->Left = MainScreen->Left;
2251 // TipButton->Glyph->LoadFromResourceName(0, "ShowLog"); //'Trains in play' new at v2.2.0
2252  OAListBox->Clear();
2253  OperatorActionPanel->Visible = false;
2254  OperatorActionPanel->Top = MainScreen->Top + MainScreen->Height - OperatorActionPanel->Height;
2255  OperatorActionPanel->Left = MainScreen->Left + MainScreen->Width - OperatorActionPanel->Width; ;
2257  AllRoutes->LockedRouteVector.clear();
2258  Level1Mode = BaseMode;
2259  SetLevel1Mode(8); // calls Clearand...
2260  Utilities->CallLogPop(1555);
2261  }
2262  catch(const Exception &e)
2263  {
2264  ErrorLog(13, e.Message);
2265  }
2266 }
2267 
2268 // ---------------------------------------------------------------------------
2269 // Menu Interface (for items not already covered above)
2270 // ---------------------------------------------------------------------------
2271 void __fastcall TInterface::LoadRailwayMenuItemClick(TObject *Sender)
2272 {
2273  try
2274  {
2275  TrainController->LogEvent("LoadRailwayMenuItemClick");
2276  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LoadRailwayMenuItemClick");
2277  if(!ClearEverything(1))
2278  {
2279  Utilities->CallLogPop(1139);
2280  return;
2281  }
2282  // LoadRailwayDialog->Filter = "Development file (*.dev)|*.dev|Railway file (*.rly)|*.rly"; //as was
2283  // changed at v2.0.0 (Embarcadero change) to show all files together
2284  LoadRailwayDialog->Filter = "Railway files (*.rly or *.dev)|*.rly; *.dev";
2285  if(LoadRailwayDialog->Execute())
2286  {
2287  if(LoadRailwayDialog->InitialDir != TPath::GetDirectoryName(LoadRailwayDialog->FileName))//new at v2.6.0 to retain a new directory
2288  {
2289  LoadRailwayDialog->InitialDir = TPath::GetDirectoryName(LoadRailwayDialog->FileName);
2290  SaveRailwayDialog->InitialDir = TPath::GetDirectoryName(LoadRailwayDialog->FileName);
2291  }
2292  TrainController->LogEvent("LoadRailway " + AnsiString(LoadRailwayDialog->FileName));
2293  LoadRailway(0, AnsiString(LoadRailwayDialog->FileName));
2294  }
2295  // else ShowMessage("Load Aborted"); drop this
2296  // Display->Update(); //display updated in ClearandRebuildRailway
2297  Track->CalcHLocMinEtc(9);
2298  Level1Mode = BaseMode;
2301  SetLevel1Mode(11); // calls Clearand... to plot the new railway
2302  Utilities->CallLogPop(31);
2303  }
2304  catch(const Exception &e)
2305  {
2306  ErrorLog(17, e.Message);
2307  }
2308 }
2309 // ---------------------------------------------------------------------------
2310 
2311 void TInterface::LoadRailway(int Caller, AnsiString LoadFileName)
2312 { // display of the loaded railway covered in the calling routine
2313  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadRailway," + LoadFileName);
2314  if(FileIntegrityCheck(0, LoadFileName.c_str()))
2315  {
2316  Screen->Cursor = TCursor(-11); // Hourglass;
2317  std::ifstream VecFile(LoadFileName.c_str());
2318  if(!(VecFile.fail()))
2319  {
2320  AnsiString TempString = Utilities->LoadFileString(VecFile); // version number
2321  int TempOffsetHHome = Utilities->LoadFileInt(VecFile);
2322  int TempOffsetVHome = Utilities->LoadFileInt(VecFile);
2323  bool GraphicsFollow = false;
2324  // can't load DisplayOffsetH & VHome until after LoadTrack as that calls TrackClear & zeroes them
2325 // load track elements
2326  Track->LoadTrack(1, VecFile, GraphicsFollow);
2327 // load text elements
2328  TextHandler->LoadText(0, VecFile);
2329 // load PrefDir elements
2330  EveryPrefDir->LoadPrefDir(0, VecFile);
2331  if(GraphicsFollow)
2332  {
2333 // load user graphics
2334  Track->LoadGraphics(0, VecFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME); // include path to Graphics folder
2335  }
2336  EveryPrefDir->CheckPrefDirAgainstTrackVector(0); // clears PrefDir if any discrepancies found
2337  VecFile.close();
2338  Display->DisplayOffsetHHome = TempOffsetHHome;
2339  Display->DisplayOffsetVHome = TempOffsetVHome;
2341 
2342  TFont *TempFont = new TFont; // if try to alter MainScreen->Canvas->Font directly it won't change the style for some reason
2343  TempFont->Style.Clear();
2344  TempFont->Name = "MS Sans Serif"; // reset font, else stays set to last displayed text font
2345  TempFont->Size = 10;
2346  TempFont->Color = clB0G0R0;
2347  TempFont->Charset = (TFontCharset)(0);
2348  MainScreen->Canvas->Font->Assign(TempFont);
2349  delete TempFont;
2350 
2351 // calculate starting zoomed out offset values - same as when zoom out button clicked
2352  int OVOffH_NVCentre = Display->DisplayOffsetH - (1.5 * Utilities->ScreenElementWidth);
2353 // start zoomout centre at DisplayOffsetH + 30 - zoomout width/2 = -(1.5 * 60)
2354  int LeftExcess = OVOffH_NVCentre - Track->GetHLocMin();
2355  int RightExcess = Track->GetHLocMax() - OVOffH_NVCentre - ((4 * Utilities->ScreenElementWidth) - 1);
2356  if((LeftExcess > 0) && (RightExcess > 0))
2357  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre;
2358  else if((LeftExcess > 0) && (RightExcess <= 0))
2359  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre + ((RightExcess) / (Utilities->ScreenElementWidth / 2)) *
2360  (Utilities->ScreenElementWidth / 2); // normalise to nearest half screen
2361  else if((LeftExcess <= 0) && (RightExcess > 0))
2362  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre - ((LeftExcess) / (Utilities->ScreenElementWidth / 2)) * (Utilities->ScreenElementWidth / 2);
2363  else
2364  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre; // no excess at either side, so display in centre
2365 
2366  int OVOffV_NVCentre = Display->DisplayOffsetV - (1.5 * Utilities->ScreenElementHeight);
2367  int TopExcess = OVOffV_NVCentre - Track->GetVLocMin();
2368  int BotExcess = Track->GetVLocMax() - OVOffV_NVCentre - ((4 * Utilities->ScreenElementHeight) - 1);
2369  if((TopExcess > 0) && (BotExcess > 0))
2370  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre;
2371  else if((TopExcess > 0) && (BotExcess <= 0))
2372  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre + ((BotExcess) / (Utilities->ScreenElementHeight / 2)) *
2373  (Utilities->ScreenElementHeight / 2); // normalise to nearest half screen
2374  else if((TopExcess <= 0) && (BotExcess > 0))
2375  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre - ((TopExcess) / (Utilities->ScreenElementHeight / 2)) * (Utilities->ScreenElementHeight / 2);
2376  else
2377  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre; // no excess at either side, so display in centre
2378 // all above same as when zoom out button clicked
2379  Display->DisplayZoomOutOffsetVHome = Display->DisplayZoomOutOffsetV; // now set zoomed out 'home' values
2381 
2382  SavedFileName = AnsiString(LoadRailwayDialog->FileName); // includes the full PrefDir
2383  if(SavedFileName != "") // shouldn't be "" at this stage but leave in as a safeguard
2384  {
2385  char LastChar = SavedFileName[SavedFileName.Length()];
2386  if((LastChar == 'y') || (LastChar == 'Y'))
2387  {
2388  if(!(Track->IsReadyForOperation()))
2389  {
2390  ShowMessage("Railway not ready for operation so unable to load as a .rly file. Loading as a new railway under development");
2391  SavedFileName = "";
2392  RlyFile = false;
2393  RailwayTitle = "";
2394  TimetableTitle = "";
2395  SetCaption(5);
2396  Track->CalcHLocMinEtc(1);
2397  Screen->Cursor = TCursor(-2); // Arrow
2398  Level1Mode = BaseMode;
2399  SetLevel1Mode(9);
2400  Utilities->CallLogPop(1136);
2401  return;
2402  }
2403  else
2404  {
2405  RlyFile = true;
2406  }
2407  }
2408  else
2409  {
2410  RlyFile = false;
2411  }
2412  }
2413  else
2414  {
2415  RlyFile = false;
2416  }
2417  FileChangedFlag = false;
2418  for(int x = AnsiString(LoadRailwayDialog->FileName).Length(); x > 0; x--)
2419  {
2420  if(AnsiString(LoadRailwayDialog->FileName)[x] == '\\')
2421  {
2422  RailwayTitle = AnsiString(LoadRailwayDialog->FileName).SubString(x + 1, AnsiString(LoadRailwayDialog->FileName).Length() - x - 4);
2423  TimetableTitle = "";
2424  SetCaption(6);
2425  break;
2426  }
2427  }
2428  } // if(VecFile)
2429  else
2430  ShowMessage("File open failed prior to load");
2431  Screen->Cursor = TCursor(-2); // Arrow
2432  } // if(FileIntegrityCheck(LoadRailwayDialog->FileName.c_str()))
2433  else
2434  ShowMessage("File integrity check failed - unable to load");
2435  Utilities->CallLogPop(1774);
2436 }
2437 
2438 // ---------------------------------------------------------------------------
2439 
2440 void __fastcall TInterface::SaveMenuItemClick(TObject *Sender)
2441 {
2442 // save under existing name
2443 // no need to alter RlyFile for saving under existing name
2444 
2445  try
2446  {
2447  TrainController->LogEvent("SaveMenuItemClick, " + SavedFileName);
2448  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveMenuItemClick");
2449  Screen->Cursor = TCursor(-11); // Hourglass;
2450  std::ofstream VecFile(SavedFileName.c_str());
2451  if(!(VecFile.fail()))
2452  {
2456  // save track elements
2457  if(Track->UserGraphicVector.empty())
2458  {
2459  Track->SaveTrack(3, VecFile, false); // false for no graphics (**Active elements** saved as marker)
2460  }
2461  else
2462  {
2463  Track->SaveTrack(8, VecFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
2464  }
2465  // save text elements
2466  TextHandler->SaveText(0, VecFile);
2467  // save PrefDir elements
2468  EveryPrefDir->SavePrefDirVector(0, VecFile);
2469  if(!Track->UserGraphicVector.empty())
2470  {
2471  // save user graphics
2472  Track->SaveUserGraphics(0, VecFile);
2473  }
2474  FileChangedFlag = false;
2475  VecFile.close();
2476  }
2477  else
2478  ShowMessage("File open failed prior to save");
2479  Screen->Cursor = TCursor(-2); // Arrow
2480  Level1Mode = BaseMode;
2481  SetLevel1Mode(12); // to disable the save option
2482  Utilities->CallLogPop(1178);
2483  }
2484  catch(const Exception &e)
2485  {
2486  ErrorLog(135, e.Message);
2487  }
2488 }
2489 
2490 // ---------------------------------------------------------------------------
2491 void __fastcall TInterface::SaveAsMenuItemClick(TObject *Sender)
2492 {
2493  try
2494  {
2495  TrainController->LogEvent("SaveAsMenuItemClick");
2496  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveAsMenuItemClick");
2497  SaveAsSubroutine(0);
2498  Utilities->CallLogPop(32);
2499  }
2500  catch(const Exception &e)
2501  {
2502  ErrorLog(18, e.Message);
2503  }
2504 }
2505 
2506 // ---------------------------------------------------------------------------
2507 
2508 void __fastcall TInterface::SaveImageNoGridMenuItemClick(TObject *Sender)
2509 { // need to stop clock in case invoke during operation
2510  try
2511  {
2512  TrainController->LogEvent("SaveImageNoGridMenuItemClick");
2513  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveImageNoGridMenuItemClick");
2514  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2515  {
2516  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2517  Utilities->CallLogPop(1695);
2518  return;
2519  }
2520  Screen->Cursor = TCursor(-11); // Hourglass;
2521  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2523  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2524  // format "16/06/2009 20:55:17"
2525  // avoid characters in filename:= / \ : * ? " < > |
2526  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; " + RailwayTitle + ".bmp";
2527  AnsiString ShortName = "";
2528  for(int x = ImageFileName.Length(); x > 0; x--)
2529  {
2530  if(ImageFileName[x] == '\\')
2531  {
2532  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2533  break;
2534  }
2535  }
2536  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2537  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2538  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2539 
2540  int HPosMin = Track->GetHLocMin() * 16;
2541  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2542  int VPosMin = Track->GetVLocMin() * 16;
2543  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2544  RailwayImage->Width = HPosMax - HPosMin;
2545  RailwayImage->Height = VPosMax - VPosMin;
2546 
2547  // need to check if there is any text that extends past HPosMax or below VPosMax
2548  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2549  if(!TextHandler->TextVector.empty())
2550  {
2551  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2552  {
2553  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2554  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2555  if(NewWidth > RailwayImage->Width)
2556  {
2557  RailwayImage->Width = NewWidth;
2558  }
2559  if(NewHeight > RailwayImage->Height)
2560  {
2561  RailwayImage->Height = NewHeight;
2562  }
2563  }
2564  }
2565 
2566  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2567  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2568  RailwayImage->Canvas->FillRect(Rect);
2569 
2570  // write graphics first so text & track overwrite
2571  Track->WriteGraphicsToImage(0, RailwayImage);
2572  // then write text so track overwrites
2573  TextHandler->WriteTextToImage(0, RailwayImage);
2574  Track->WriteTrackToImage(0, RailwayImage);
2575 
2576  RailwayImage->SaveToFile(ImageFileName);
2577  delete RailwayImage;
2578  TrainController->BaseTime = TDateTime::CurrentDateTime();
2580  Screen->Cursor = TCursor(-2); // Arrow
2581  Utilities->CallLogPop(1535);
2582  }
2583  catch(const Exception &e)
2584  {
2585  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2586  {
2587  Screen->Cursor = TCursor(-2); // Arrow;
2588  UnicodeString MessageStr = "Insufficient memory available to store this image";
2589  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2590  }
2591  else
2592  {
2593  ErrorLog(42, e.Message);
2594  }
2595  }
2596 }
2597 
2598 // ---------------------------------------------------------------------------
2599 
2600 void __fastcall TInterface::SaveImageAndGridMenuItemClick(TObject *Sender)
2601 { // need to stop clock in case invoke during operation
2602  try
2603  {
2604  TrainController->LogEvent("SaveImageAndGridMenuItemClick");
2605  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveImageAndGridMenuItemClick");
2606  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2607  {
2608  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2609  Utilities->CallLogPop(1696);
2610  return;
2611  }
2612  Screen->Cursor = TCursor(-11); // Hourglass;
2613  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2615  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2616  // format "16/06/2009 20:55:17"
2617  // avoid characters in filename:= / \ : * ? " < > |
2618  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; " + RailwayTitle + ".bmp";
2619  AnsiString ShortName = "";
2620  for(int x = ImageFileName.Length(); x > 0; x--)
2621  {
2622  if(ImageFileName[x] == '\\')
2623  {
2624  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2625  break;
2626  }
2627  }
2628  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2629  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2630  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2631  int HPosMin = Track->GetHLocMin() * 16;
2632  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2633  int VPosMin = Track->GetVLocMin() * 16;
2634  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2635  RailwayImage->Width = HPosMax - HPosMin;
2636  RailwayImage->Height = VPosMax - VPosMin;
2637 
2638  // need to check if there is any text that extends past HPosMax or below VPosMax
2639  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2640  if(!TextHandler->TextVector.empty())
2641  {
2642  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2643  {
2644  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2645  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2646  if(NewWidth > RailwayImage->Width)
2647  {
2648  RailwayImage->Width = NewWidth;
2649  }
2650  if(NewHeight > RailwayImage->Height)
2651  {
2652  RailwayImage->Height = NewHeight;
2653  }
2654  }
2655  }
2656 
2657  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2658  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2659  RailwayImage->Canvas->FillRect(Rect);
2660 
2661  // write the grid first so all else on top
2662  for(int x = 0; x < ((RailwayImage->Width) / 16); x++)
2663  {
2664  for(int y = 0; y < ((RailwayImage->Height) / 16); y++)
2665  {
2666  RailwayImage->Canvas->Draw((x * 16), (y * 16), RailGraphics->bmGrid); // graphic is black on white so no need to change
2667  }
2668  }
2669  // write graphics next so text & track overwrite
2670  Track->WriteGraphicsToImage(1, RailwayImage);
2671  // then write text so track overwrites
2672  TextHandler->WriteTextToImage(1, RailwayImage);
2673  Track->WriteTrackToImage(1, RailwayImage);
2674  RailwayImage->SaveToFile(ImageFileName);
2675  delete RailwayImage;
2676  TrainController->BaseTime = TDateTime::CurrentDateTime();
2678  Screen->Cursor = TCursor(-2); // Arrow
2679  Utilities->CallLogPop(1536);
2680  }
2681  catch(const Exception &e)
2682  {
2683  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2684  {
2685  Screen->Cursor = TCursor(-2); // Arrow;
2686  UnicodeString MessageStr = "Insufficient memory available to store this image";
2687  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2688  }
2689  else
2690  {
2691  ErrorLog(43, e.Message);
2692  }
2693  }
2694 }
2695 // ---------------------------------------------------------------------------
2696 
2697 void __fastcall TInterface::SaveImageAndPrefDirsMenuItemClick(TObject *Sender)
2698 { // need to stop clock in case invoke during operation
2699  try
2700  {
2701  TrainController->LogEvent("SaveImageAndPrefDirsMenuItemClick");
2702  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveImageAndPrefDirsMenuItemClick");
2703  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2704  {
2705  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2706  Utilities->CallLogPop(1697);
2707  return;
2708  }
2709  Screen->Cursor = TCursor(-11); // Hourglass;
2710  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2712  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2713  // format "16/06/2009 20:55:17"
2714  // avoid characters in filename:= / \ : * ? " < > |
2715  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; " + RailwayTitle + ".bmp";
2716  AnsiString ShortName = "";
2717  for(int x = ImageFileName.Length(); x > 0; x--)
2718  {
2719  if(ImageFileName[x] == '\\')
2720  {
2721  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2722  break;
2723  }
2724  }
2725  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2726  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2727  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2728  int HPosMin = Track->GetHLocMin() * 16;
2729  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2730  int VPosMin = Track->GetVLocMin() * 16;
2731  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2732  RailwayImage->Width = HPosMax - HPosMin;
2733  RailwayImage->Height = VPosMax - VPosMin;
2734 
2735  // need to check if there is any text that extends past HPosMax or below VPosMax
2736  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2737  if(!TextHandler->TextVector.empty())
2738  {
2739  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2740  {
2741  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2742  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2743  if(NewWidth > RailwayImage->Width)
2744  {
2745  RailwayImage->Width = NewWidth;
2746  }
2747  if(NewHeight > RailwayImage->Height)
2748  {
2749  RailwayImage->Height = NewHeight;
2750  }
2751  }
2752  }
2753 
2754  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2755  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2756  RailwayImage->Canvas->FillRect(Rect);
2757 
2758  // write graphics first so text & track overwrite
2759  Track->WriteGraphicsToImage(2, RailwayImage);
2760  // then write text so track overwrites
2761  TextHandler->WriteTextToImage(2, RailwayImage);
2762  Track->WriteTrackToImage(2, RailwayImage);
2763  EveryPrefDir->WritePrefDirToImage(0, RailwayImage);
2764  RailwayImage->SaveToFile(ImageFileName);
2765  delete RailwayImage;
2766  TrainController->BaseTime = TDateTime::CurrentDateTime();
2768  Screen->Cursor = TCursor(-2); // Arrow
2769  Utilities->CallLogPop(1566);
2770  }
2771  catch(const Exception &e)
2772  {
2773  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2774  {
2775  Screen->Cursor = TCursor(-2); // Arrow;
2776  UnicodeString MessageStr = "Insufficient memory available to store this image";
2777  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2778  }
2779  else
2780  {
2781  ErrorLog(45, e.Message);
2782  }
2783  }
2784 }
2785 // ---------------------------------------------------------------------------
2786 
2787 void __fastcall TInterface::SaveOperatingImageMenuItemClick(TObject *Sender)
2788 { // need to stop clock
2789  try
2790  {
2791  TrainController->LogEvent("SaveOperatingImageMenuItemClick");
2792  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveOperatingImageMenuItemClick");
2793  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2794  {
2795  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2796  Utilities->CallLogPop(1702);
2797  return;
2798  }
2799  Screen->Cursor = TCursor(-11); // Hourglass;
2800  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2802 
2803  AnsiString TimetableTimeStr = Utilities->Format96HHMMSS(TrainController->TTClockTime);
2804  TimetableTimeStr = TimetableTimeStr.SubString(1, 2) + '.' + TimetableTimeStr.SubString(4, 2) + '.' + TimetableTimeStr.SubString(7, 2);
2805  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2806  // format "16/06/2009 20:55:17"
2807  // avoid characters in filename:= / \ : * ? " < > |
2808  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; Timetable time " + TimetableTimeStr + "; " + RailwayTitle +
2809  "; " + TimetableTitle + ".bmp";
2810  AnsiString ShortName = "";
2811  for(int x = ImageFileName.Length(); x > 0; x--)
2812  {
2813  if(ImageFileName[x] == '\\')
2814  {
2815  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2816  break;
2817  }
2818  }
2819  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2820  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2821  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2822  int HPosMin = Track->GetHLocMin() * 16;
2823  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2824  int VPosMin = Track->GetVLocMin() * 16;
2825  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2826  RailwayImage->Width = HPosMax - HPosMin;
2827  RailwayImage->Height = VPosMax - VPosMin;
2828 
2829  // need to check if there is any text that extends past HPosMax or below VPosMax
2830  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2831  if(!TextHandler->TextVector.empty())
2832  {
2833  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2834  {
2835  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2836  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2837  if(NewWidth > RailwayImage->Width)
2838  {
2839  RailwayImage->Width = NewWidth;
2840  }
2841  if(NewHeight > RailwayImage->Height)
2842  {
2843  RailwayImage->Height = NewHeight;
2844  }
2845  }
2846  }
2847 
2848  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2849  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2850  RailwayImage->Canvas->FillRect(Rect);
2851 
2852  // write graphics first so text & track overwrite
2853  Track->WriteGraphicsToImage(3, RailwayImage);
2854  // then write text so track overwrites
2855  TextHandler->WriteTextToImage(3, RailwayImage);
2856  Track->WriteOperatingTrackToImage(0, RailwayImage); // need points with single fillets, signals with colours, gaps all connected
2857  AllRoutes->WriteAllRoutesToImage(0, RailwayImage);
2858 // add any locked route markers
2859  if(!AllRoutes->LockedRouteVector.empty())
2860  {
2861  for(TAllRoutes::TLockedRouteVectorIterator LRVIT = AllRoutes->LockedRouteVector.end() - 1; LRVIT >= AllRoutes->LockedRouteVector.begin(); LRVIT--)
2862  {
2863  TOneRoute Route = AllRoutes->GetFixedRouteAt(167, LRVIT->RouteNumber);
2864  int x = Route.PrefDirSize() - 1;
2865  bool BreakFlag = false;
2866  TPrefDirElement PrefDirElement = Route.GetFixedPrefDirElementAt(188, x);
2867  while(PrefDirElement.GetTrackVectorPosition() != LRVIT->TruncateTrackVectorPosition)
2868  {
2869  RailwayImage->Canvas->Draw((PrefDirElement.HLoc - Track->GetHLocMin()) * 16, (PrefDirElement.VLoc - Track->GetVLocMin()) * 16,
2870  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
2871  if(!(AllRoutes->TrackIsInARoute(13, PrefDirElement.Conn[PrefDirElement.GetELinkPos()],
2872  PrefDirElement.ConnLinkPos[PrefDirElement.GetELinkPos()])))
2873  {
2874  BreakFlag = true;
2875  break; // train removed earlier element from route so stop here
2876  }
2877  x--;
2878  PrefDirElement = Route.GetFixedPrefDirElementAt(180, x);
2879  }
2880  if(!BreakFlag)
2881  {
2882  if(PrefDirElement.GetTrackVectorPosition() == LRVIT->TruncateTrackVectorPosition)
2883  {
2884  RailwayImage->Canvas->Draw((PrefDirElement.HLoc - Track->GetHLocMin()) * 16, (PrefDirElement.VLoc - Track->GetVLocMin()) * 16,
2885  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
2886  }
2887  }
2888  }
2889  }
2890  TrainController->WriteTrainsToImage(0, RailwayImage);
2891  RailwayImage->SaveToFile(ImageFileName);
2892  delete RailwayImage;
2893  TrainController->BaseTime = TDateTime::CurrentDateTime();
2895  Screen->Cursor = TCursor(-2); // Arrow
2896  Utilities->CallLogPop(1703);
2897  }
2898  catch(const Exception &e)
2899  {
2900  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2901  {
2902  Screen->Cursor = TCursor(-2); // Arrow;
2903  UnicodeString MessageStr = "Insufficient memory available to store this image";
2904  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2905  }
2906  else
2907  {
2908  ErrorLog(113, e.Message); //NB: DO NOT CHANGE THIS ERROR NUMBER - THE DISPLAYED MESSAGE DEPENDS ON IT
2909  }
2910  }
2911 }
2912 
2913 // ---------------------------------------------------------------------------
2914 
2915 void __fastcall TInterface::SaveHeaderMenu1Click(TObject *Sender)
2916 {
2917 //
2918  try
2919  {
2920  TrainController->LogEvent("SaveHeaderMenu1Click");
2921  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveHeaderMenu1Click");
2922  if(Sender == SaveSessionButton)
2923  {
2924  SaveSessionFlag = true;
2925  }
2926  else if(SavedFileName == "") // use 'Save As' function
2927  {
2928  SaveAsSubroutine(1);
2929  }
2930  else // ordinary save
2931  {
2932  Screen->Cursor = TCursor(-11); // Hourglass;
2933  std::ofstream VecFile(SavedFileName.c_str());
2934  if(!(VecFile.fail()))
2935  {
2939  // save track elements
2940  if(Track->UserGraphicVector.empty())
2941  {
2942  Track->SaveTrack(9, VecFile, false); // false for no graphics (**Active elements** saved as marker)
2943  }
2944  else
2945  {
2946  Track->SaveTrack(10, VecFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
2947  }
2948  // save text elements
2949  TextHandler->SaveText(5, VecFile);
2950  // save PrefDir elements
2951  EveryPrefDir->SavePrefDirVector(8, VecFile);
2952  if(!Track->UserGraphicVector.empty())
2953  {
2954  // save user graphics
2955  Track->SaveUserGraphics(1, VecFile);
2956  }
2957  FileChangedFlag = false;
2958  VecFile.close();
2959  }
2960  else
2961  ShowMessage("Railway failed to save - can't open file");
2962  Screen->Cursor = TCursor(-2); // Arrow
2963  }
2964  Utilities->CallLogPop(1552);
2965  }
2966  catch(const Exception &e)
2967  {
2968  ErrorLog(44, e.Message);
2969  }
2970 }
2971 
2972 // ---------------------------------------------------------------------------
2973 void __fastcall TInterface::LoadSessionMenuItemClick(TObject *Sender)
2974 {
2975  try
2976  {
2977  TrainController->LogEvent("LoadSessionMenuItemClick");
2978  LoadSessionFlag = true; // load session within ClockTimer2
2979  }
2980  catch(const Exception &e)
2981  {
2982  ErrorLog(136, e.Message);
2983  }
2984 }
2985 
2986 // ---------------------------------------------------------------------------
2987 void __fastcall TInterface::ClearAllMenuItemClick(TObject *Sender)
2988 {
2989  try
2990  {
2991  TrainController->LogEvent("ClearAllMenuItemClick");
2992  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ClearAllMenuItemClick");
2993  if(ClearEverything(2))
2994  {;
2995  } // no change in action on result
2996  Level1Mode = BaseMode;
2997  SetLevel1Mode(126);
2998  Utilities->CallLogPop(1179);
2999  }
3000  catch(const Exception &e)
3001  {
3002  ErrorLog(137, e.Message);
3003  }
3004 }
3005 
3006 // ---------------------------------------------------------------------------
3007 void __fastcall TInterface::ExportTTMenuItemClick(TObject *Sender)
3008 { // no need to stop clock as can't be called when railway operating
3009  try
3010  {
3011  TrainController->LogEvent("ExportTTMenuItemClick");
3012  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExportTTMenuItemClick");
3013  if(!DirectoryExists(CurDir + "\\" + FORMATTEDTT_DIR_NAME))
3014  {
3015  ShowMessage("Failed to find folder " + FORMATTEDTT_DIR_NAME + " in the folder where 'railway.exe' resides. Timetable can't be exported");
3016  Utilities->CallLogPop(1699);
3017  return;
3018  }
3019 // Screen->Cursor = TCursor(-11); // Hourglass; - no good setting here as it's reset by ShowMessage in CreateFormattedTimetable. It's set there after
3020 // the message instead, but reset here afterwards
3021  // no need to stop clock as can't select this if operating
3023  Screen->Cursor = TCursor(-2); // Arrow - reset after above function returns
3024  Utilities->CallLogPop(1573);
3025  }
3026  catch(const Exception &e)
3027  {
3028  ErrorLog(138, e.Message);
3029  }
3030 }
3031 // ---------------------------------------------------------------------------
3032 // Timetable editing functions
3033 
3034 /* Note that during early development the timetable was created outside the program as a .csv file using Excel, it was only later that
3035  the editing functions within the program were developed. Much of the original structure was preserved though to avoid rewriting the
3036  code interpretation functions in TrainUnit.cpp. This is why commas are used as service event separators, and why it is necessary to
3037  convert them to CRLFs for display and back again for internal storage. It is acknowledged that all this makes the editing functions
3038  somewhat cumbersome, and, as ever, if I was starting again I wouldn't do it like that!
3039 
3040  CR & LF review:
3041  These cause problems by the way that different subroutines handle them.
3042 
3043  AnsiStrings can incorporate CRLFs, but the end of an AnsiString is marked by a '\0' character as in 'C' strings.
3044 
3045  In the fstream functions 'getline(char_type* s, streamsize n)' extracts characters from the stream and puts them in buffer 's' until
3046  (a) n-1 characters are stored + '\0' after the n-1 characters;
3047  (b) a '\n' (CRLF) character is found in the stream, in which case a '\0' is added to the buffer after the text that immediately
3048  precedes the CRLF in the stream; and
3049  (c) an eof() is found in the stream, in which case a '\0' is added to the buffer at the end of the text.
3050  Note that if no characters are stored a '\0' is still stored in position [0] of the buffer.
3051 
3052  The << operator in ofstreams, when used with a null terminated string, doesn't store the null. If it is required it has to be
3053  sent explicitly, e.g. file << '\0'. Presumably the same applies for CRLF terminated strings.
3054 
3055 */
3056 // ---------------------------------------------------------------------------
3057 
3058 void __fastcall TInterface::CreateTimetableMenuItemClick(TObject *Sender)
3059 {
3060  try
3061  {
3062  TrainController->LogEvent("CreateTimetableMenuItemClick");
3063  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CreateTimetableMenuItemClick");
3064  CreateEditTTFileName = "";
3065  TimetableEditVector.clear();
3066  TimetableEditPanel->Visible = true;
3067  TrainController->TTEditPanelVisible = true; //added at v2.6.0 for two location message
3068  HighlightPanel->Visible = false;
3069  TimetablePanel->Visible = true;
3070  TimetablePanel->BringToFront(); // in case SaveRailway button visible, want it hidden else obscures the panel text
3071  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
3072  OneEntryTimetableMemo->Clear();
3073  AllEntriesTTListBox->Clear();
3074  TTStartTimeBox->Text = "";
3075  AddSubMinsBox->Text = "";
3077  LocationNameComboBox->Clear();
3078  TimetableTitle = ""; // unload any loaded timetable. Added here at v2.1.0
3079  TrainController->TrainDataVector.clear(); // unload any loaded timetable. Added here at v2.1.0
3080  SetCaption(9); // added at v2.1.0 as formerly retained earlier loaded tt name in error
3081  TimetableChangedFlag = false;
3082  TimetableValidFlag = false;
3083  TTEntryChangedFlag = false;
3085  AZOrderButton->Caption = AnsiString("A-Z Order");
3086  AZOrderButton->Hint = AnsiString("Arrange services in alphabetical order Toggle with Shift+ Z");
3087  CopiedEntryFlag = false;
3088  NewEntryInPreparationFlag = false;
3089  CopiedEntryStr = "";
3090  TEVPtr = 0;
3092  TTFirstServicePtr = 0;
3093  TTLastServicePtr = 0; // all set to null to begin with
3094 
3095 // populate LocationNameComboBox if a railway is loaded, but first compile the ActiveTrackElementNameMap
3096  TTrack::TActiveTrackElementNameMapEntry ActiveTrackElementNameMapEntry;
3098  for(unsigned int x = 0; x < Track->TrackVector.size(); x++)
3099  {
3100  if((Track->TrackVector.at(x).ActiveTrackElementName != "") && (Track->ContinuationNameMap.find(Track->TrackVector.at(x).ActiveTrackElementName))
3101  == Track->ContinuationNameMap.end())
3102  { // exclude any name that appears in a continuation, error message given in tt validation if try to include such a name in a tt
3103  ActiveTrackElementNameMapEntry.first = Track->TrackVector.at(x).ActiveTrackElementName;
3104  ActiveTrackElementNameMapEntry.second = 0; // this is a dummy value
3105  Track->ActiveTrackElementNameMap.insert(ActiveTrackElementNameMapEntry);
3106  }
3107  }
3109  if(!(Track->ActiveTrackElementNameMap.empty()))
3110  {
3111  LocationNameComboBox->Text = "Location names";
3112 // new version at beta v0.2b
3114  ATENIT++)
3115  {
3116  LocationNameComboBox->Items->Add(ATENIT->first); // continuations excluded during compilation, but a location that includes
3117  // continuations as well as other track will be included - earlier version
3118  // would have excluded them
3119  }
3120 
3121 /* old version using LocationNameMultiMap, changed to use ActiveTrackElementNames to avoid including lone concourses and named non-station
3122  locations
3123  TStringList *StringList = new TStringList;
3124  StringList->Clear();//probably already empty but help file doesn't say so
3125  StringList->Sorted = false;//for now
3126  for(TTrack::TLocationNameMultiMapIterator LNMIT = Track->LocationNameMultiMap.begin(); LNMIT != Track->LocationNameMultiMap.end(); LNMIT++)
3127  {
3128  NewKey = LNMIT->first;
3129  if(OldKey != NewKey)//only add new values
3130  {
3131  if(Track->ContinuationNameMap.find(NewKey) == Track->ContinuationNameMap.end())//not a continuation
3132  {
3133  StringList->Add(NewKey);
3134  OldKey = NewKey;
3135  }
3136  }
3137  }
3138  StringList->Sort();
3139  for(int x=0;x<StringList->Count;x++)
3140  {
3141  LocationNameComboBox->Items->Add(StringList->Strings[x]);
3142  }
3143  delete StringList;
3144 */
3145  }
3146  else
3147  {
3148  LocationNameComboBox->Text = "No locations (listed when a railway with names is loaded)";
3149  }
3151  SetLevel1Mode(82);
3152  Utilities->CallLogPop(1595);
3153  }
3154  catch(const Exception &e)
3155  {
3156  ErrorLog(47, e.Message);
3157  }
3158 }
3159 
3160 // ---------------------------------------------------------------------------
3161 void __fastcall TInterface::EditTimetableMenuItemClick(TObject *Sender)
3162 /* The .ttb file contains a sequence of AnsiStrings separated by null characters. CRLFs may be embedded within the AnsiStrings,
3163  * to cause newlines when displayed. Each AnsiString corresponds to a timetable 'entry'
3164 */
3165 {
3166  try
3167  {
3168  TrainController->LogEvent("EditTimetableMenuItemClick");
3169  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",EditTimetableMenuItemClick");
3170  SigImagePanel->Visible = false; //stop panel showing while waiting for name entry
3171  TimetableDialog->Filter = "Timetable file (*.ttb)|*ttb";
3172  CreateEditTTFileName = "";
3173  TimetableEditVector.clear();
3174  TimetableEditPanel->Visible = true;
3175  TrainController->TTEditPanelVisible = true; //added at v2.6.0 for two location message
3176  HighlightPanel->Visible = false;
3177  TimetablePanel->Visible = true;
3178  TimetablePanel->BringToFront(); // in case SaveRailway button visible, want it hidden else obscures the panel text
3179  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
3180  OneEntryTimetableMemo->Clear();
3181  AllEntriesTTListBox->Clear();
3182  TTStartTimeBox->Text = "";
3183  AddSubMinsBox->Text = "";
3185  LocationNameComboBox->Clear();
3186  TimetableTitle = ""; // unload any loaded timetable. Moved here from below at v2.1.0 for consistency with CreateTimetable
3187  TrainController->TrainDataVector.clear(); // unload any loaded timetable. Moved here from below at v2.1.0 for consistency with CreateTimetable
3188  SetCaption(8); // added at v2.1.0 as formerly retained earlier loaded tt name in error
3189  TEVPtr = 0;
3191  TTFirstServicePtr = 0;
3192  TTLastServicePtr = 0; // all set to null to begin with
3193  if(TimetableDialog->Execute())
3194  {
3195  if(TimetableDialog->InitialDir != TPath::GetDirectoryName(TimetableDialog->FileName))//new at v2.6.0 to retain a new directory
3196  {
3197  TimetableDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
3198  SaveTTDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
3199  }
3200  CreateEditTTFileName = AnsiString(TimetableDialog->FileName);
3201  TrainController->LogEvent("EditTimetable " + CreateEditTTFileName);
3202  std::ifstream TTBLFile(CreateEditTTFileName.c_str(), std::ios_base::binary); // open in binary to examine each character
3203  if(TTBLFile.is_open())
3204  {
3205  // check doesn't contain any non-ascii characters except CR, LF & '\0', and isn't empty
3206  char c;
3207  while(!TTBLFile.eof())
3208  {
3209  TTBLFile.get(c);
3210  if((c < 32) && (c != 13) && (c != 10) && (c != '\0')) // char is signed by default so values > 127 will be caught as treated as -ve
3211  {
3212  ShowMessage("Timetable file is empty or contains non-ascii characters, codes must be between 20 and 127, or CR or LF");
3213  TTBLFile.close();
3214  Utilities->CallLogPop(1612);
3215  return;
3216  }
3217  }
3218  TTBLFile.close();
3219  }
3220  else
3221  {
3222  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
3223  Utilities->CallLogPop(1597);
3224  return;
3225  }
3226  // reopen again in binary mode so the "\r\n" pairs stay as they are rather than being entered as '\n'
3227  Delay(4, 100); // 100mSec delay between closing & re-opening file
3228  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary);
3229  if(TTBLFile.is_open())
3230  {
3231  TTBLFile.clear(); // to clear eofbit from last read
3232  TTBLFile.seekg(0); // shouldn't be needed but include for safety
3233  TimetableChangedFlag = false;
3234  TimetableValidFlag = false;
3235  TTEntryChangedFlag = false;
3237  AZOrderButton->Caption = AnsiString("A-Z Order");
3238  AZOrderButton->Hint = AnsiString("Arrange services in alphabetical order Toggle with Shift+ Z");
3239  NewEntryInPreparationFlag = false;
3240  CopiedEntryStr = "";
3241  CopiedEntryFlag = false;
3242 // CreateEditTTFileName = TimetableDialog->FileName;
3243  for(int x = CreateEditTTFileName.Length(); x > 0; x--)
3244  {
3245  if(CreateEditTTFileName[x] == '\\')
3246  {
3247  CreateEditTTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
3248  break;
3249  }
3250  }
3251  char *TimetableEntryString = new char[10000];
3252  while(true)
3253  {
3254  TTBLFile.getline(TimetableEntryString, 10000, '\0'); // pick up the entire AnsiString, including any embedded newlines
3255  if(TTBLFile.eof() && (TimetableEntryString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
3256  { // may still have eof even if read a line, and
3257  // if so need to process it
3258  break;
3259  }
3260  AnsiString OneLine(TimetableEntryString);
3261  TimetableEditVector.push_back(OneLine);
3262  }
3263  TTBLFile.close();
3264  delete TimetableEntryString;
3265  // here with TimetableEditVector compiled
3266  }
3267  else
3268  {
3269  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
3270  Utilities->CallLogPop(1654);
3271  return;
3272  }
3273  }
3274  else // cancelled dialog [section prior to CallLogPop added for v1.3.2 to clear timetable screen if cancel button pressed]
3275  {
3276  CreateEditTTFileName = "";
3277 // set to null to allow a check during error file saving, if not null save the tt being edited to the file (see entry in ExitTTModeButtonClick)
3278  CreateEditTTTitle = ""; // as above
3279  Level1Mode = BaseMode;
3280  SetLevel1Mode(132);
3281  Utilities->CallLogPop(1633);
3282  return;
3283  }
3284 
3286  if(TimetableEditVector.empty())
3287  {
3289  SetLevel1Mode(89);
3290  Utilities->CallLogPop(1614);
3291  return;
3292  }
3293 
3294 // all now set where can be
3296 
3297 // populate LocationNameComboBox if a railway is loaded, but first compile the ActiveTrackElementNameMap
3298  TTrack::TActiveTrackElementNameMapEntry ActiveTrackElementNameMapEntry;
3300  for(unsigned int x = 0; x < Track->TrackVector.size(); x++)
3301  {
3302  if((Track->TrackVector.at(x).ActiveTrackElementName != "") && (Track->ContinuationNameMap.find(Track->TrackVector.at(x).ActiveTrackElementName))
3303  == Track->ContinuationNameMap.end())
3304  { // exclude any name that appears in a continuation, error message given in tt validation if try to include such a name in a tt
3305  ActiveTrackElementNameMapEntry.first = Track->TrackVector.at(x).ActiveTrackElementName;
3306  ActiveTrackElementNameMapEntry.second = 0; // this is a dummy value
3307  Track->ActiveTrackElementNameMap.insert(ActiveTrackElementNameMapEntry);
3308  }
3309  }
3311  if(!(Track->ActiveTrackElementNameMap.empty()))
3312  {
3313  LocationNameComboBox->Text = "Location names";
3314 // new version for beta v0.2b
3316  ATENIT++)
3317  {
3318  LocationNameComboBox->Items->Add(ATENIT->first); // continuations excluded during compilation, but a location that includes
3319  // continuations as well as other track will be included - earlier version
3320  // would have excluded them
3321  }
3322  }
3323  else
3324  {
3325  LocationNameComboBox->Text = "No locations (listed when a railway with names is loaded)";
3326  }
3328  SetLevel1Mode(83);
3329  Utilities->CallLogPop(1596);
3330  }
3331  catch(const Exception &e)
3332  {
3333  ErrorLog(48, e.Message);
3334  }
3335 }
3336 // ---------------------------------------------------------------------------
3337 
3338 void __fastcall TInterface::ShowHideTTButtonClick(TObject *Sender)
3339 {
3340  try
3341  {
3342  TrainController->LogEvent("ShowHideTTButtonClick");
3343  if(TimetableEditPanel->Visible)
3344  {
3345  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Show");
3346  TimetableEditPanel->Visible = false;
3347  TrainController->TTEditPanelVisible = false; //added at v2.6.0 for two location message
3348  ShowHideTTButton->Hint = "Show the timetable editor Shift S";
3349 // InfoPanel->Visible = false; //changed at v1.3.0 to make it clearer that still in TT mode
3350  InfoPanel->Caption = "Timetable mode: editor hidden"; // as above
3351  }
3352  else
3353  {
3354  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
3355  TimetableEditPanel->Visible = true;
3356  TrainController->TTEditPanelVisible = true; //added at v2.6.0 for two location message
3357  ShowHideTTButton->Hint = "Hide the timetable editor to see the railway Shift H";
3359  SetLevel1Mode(124);
3360  }
3361  }
3362  catch(const Exception &e)
3363  {
3364  ErrorLog(139, e.Message);
3365  }
3366 }
3367 // ---------------------------------------------------------------------------
3368 
3369 void __fastcall TInterface::NextTTEntryButtonClick(TObject *Sender)
3370 {
3371  try
3372  {
3373  TrainController->LogEvent("NextTTEntryButtonClick");
3374  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NextTTEntryButtonClick");
3375  if((TTCurrentEntryPtr == 0) || TimetableEditVector.empty())
3376  {
3377  Utilities->CallLogPop(1683);
3378  return;
3379  }
3380  if(TTCurrentEntryPtr < (TimetableEditVector.end() - 1))
3382  TTEntryChangedFlag = false;
3383  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3384  // position changing in AllEntriesTTListBox
3386  SetLevel1Mode(85);
3387  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3388  {
3390  }
3391  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3392  {
3393  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3394  }
3395  else
3396  {
3397  AllEntriesTTListBox->TopIndex = TopPos;
3398  }
3399  Utilities->CallLogPop(1605);
3400  }
3401  catch(const Exception &e)
3402  {
3403  ErrorLog(50, e.Message);
3404  }
3405 }
3406 
3407 // ---------------------------------------------------------------------------
3408 void __fastcall TInterface::PreviousTTEntryButtonClick(TObject *Sender)
3409 {
3410  try
3411  {
3412  TrainController->LogEvent("PreviousTTEntryButtonClick");
3413  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PreviousTTEntryButtonClick");
3414  if((TTCurrentEntryPtr == 0) || TimetableEditVector.empty())
3415  {
3416  Utilities->CallLogPop(1684);
3417  return;
3418  }
3421  TTEntryChangedFlag = false;
3422  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3423  // position changing in AllEntriesTTListBox
3425  SetLevel1Mode(86);
3426  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3427  {
3429  }
3430  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3431  {
3432  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3433  }
3434  else
3435  {
3436  AllEntriesTTListBox->TopIndex = TopPos;
3437  }
3438  Utilities->CallLogPop(1607);
3439  }
3440  catch(const Exception &e)
3441  {
3442  ErrorLog(51, e.Message);
3443  }
3444 }
3445 
3446 // ---------------------------------------------------------------------------
3447 void __fastcall TInterface::NewTTEntryButtonClick(TObject *Sender)
3448 {
3449  try
3450  {
3451  TrainController->LogEvent("NewTTEntryButtonClick");
3452  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NewTTEntryButtonClick");
3453  OneEntryTimetableMemo->Clear();
3454  OneEntryTimetableMemo->SetFocus();
3457  SetLevel1Mode(103);
3458  Utilities->CallLogPop(1615);
3459  }
3460  catch(const Exception &e)
3461  {
3462  ErrorLog(52, e.Message);
3463  }
3464 }
3465 // ---------------------------------------------------------------------------
3466 
3467 void __fastcall TInterface::AddMinsButtonClick(TObject *Sender)
3468 {
3469  try
3470  {
3471  TrainController->LogEvent("AddMinsButtonClick");
3472  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddMinsButtonClick");
3473  bool ValidFlag = true;
3474  for(int x = 1; x <= AddSubMinsBox->Text.Length(); x++)
3475  {
3476  if((AddSubMinsBox->Text[x] > '9') || (AddSubMinsBox->Text[x] < '0')) // tested in TTHandler but check here as a safeguard
3477  {
3478  ValidFlag = false;
3479  break;
3480  }
3481  }
3482  if(ValidFlag)
3483  {
3484  if(AddSubMinsBox->Text.ToInt() == 0)
3485  ValidFlag = false;
3486  }
3487  if((TTCurrentEntryPtr == 0) || (*TTCurrentEntryPtr == "") || (AddSubMinsBox->Text == "") || !ValidFlag)
3488  {
3489  Utilities->CallLogPop(1649);
3490  return;
3491  }
3492  TDateTime DummyTime;
3493  int AddMins = AddSubMinsBox->Text.ToInt();
3494  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
3495  {
3496  for(int y = 1; y < (OneEntryTimetableMemo->Lines->Strings[x].Length() - 3); y++)
3497  {
3498  if(TrainController->CheckTimeValidity(25, OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 5), DummyTime))
3499  {
3500  int Mins = OneEntryTimetableMemo->Lines->Strings[x].SubString(y + 3, 2).ToInt();
3501  int Hrs = OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 2).ToInt();
3502  Mins += AddMins;
3503  while(Mins >= 60)
3504  {
3505  Mins -= 60;
3506  Hrs++;
3507  }
3508  if(Hrs > 95)
3509  {
3510  ShowMessage("One or more times excessive, not permitted to exceed 95 hours");
3511  Utilities->CallLogPop(1650);
3512  return;
3513  }
3514  AnsiString MinsStr = AnsiString(Mins), HrsStr = AnsiString(Hrs);
3515  if(Mins < 10)
3516  MinsStr = "0" + MinsStr;
3517  if(Hrs < 10)
3518  HrsStr = "0" + HrsStr;
3519  int StrLength = OneEntryTimetableMemo->Lines->Strings[x].Length();
3520  AnsiString NewString = OneEntryTimetableMemo->Lines->Strings[x].SubString(1, (y - 1)); // up to but not including the time
3521  NewString += HrsStr + ':' + MinsStr;
3522  NewString += OneEntryTimetableMemo->Lines->Strings[x].SubString((y + 5), (StrLength - y - 4));
3523  OneEntryTimetableMemo->Lines->Strings[x] = NewString;
3524  }
3525  }
3526  }
3527 
3528  OneEntryTimetableMemo->HideSelection = true;
3529  OneEntryTimetableMemo->SelStart = 0; // need this & next command to set cursor to the top
3530  OneEntryTimetableMemo->SelLength = 0;
3531  TimetableValidFlag = false;
3532  TimetableChangedFlag = true;
3533  TTEntryChangedFlag = true;
3535  SetLevel1Mode(91);
3536  Utilities->CallLogPop(1617);
3537  }
3538  catch(const Exception &e)
3539  {
3540  ErrorLog(54, e.Message);
3541  }
3542 }
3543 // ---------------------------------------------------------------------------
3544 
3545 void __fastcall TInterface::SubMinsButtonClick(TObject *Sender)
3546 {
3547  try
3548  {
3549  TrainController->LogEvent("SubMinsButtonClick");
3550  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SubMinsButtonClick");
3551  bool ValidFlag = true;
3552  for(int x = 1; x <= AddSubMinsBox->Text.Length(); x++)
3553  {
3554  if((AddSubMinsBox->Text[x] > '9') || (AddSubMinsBox->Text[x] < '0')) // tested in TTHandler but check here as a safeguard
3555  {
3556  ValidFlag = false;
3557  break;
3558  }
3559  }
3560  if(ValidFlag)
3561  {
3562  if(AddSubMinsBox->Text.ToInt() == 0)
3563  ValidFlag = false;
3564  }
3565  if((TTCurrentEntryPtr == 0) || (*TTCurrentEntryPtr == "") || (AddSubMinsBox->Text == "") || !ValidFlag)
3566  {
3567  Utilities->CallLogPop(1659);
3568  return;
3569  }
3570  TDateTime DummyTime;
3571  int SubMins = AddSubMinsBox->Text.ToInt();
3572  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
3573  {
3574  for(int y = 1; y < (OneEntryTimetableMemo->Lines->Strings[x].Length() - 3); y++)
3575  {
3576  if(TrainController->CheckTimeValidity(28, OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 5), DummyTime))
3577  {
3578  int Mins = OneEntryTimetableMemo->Lines->Strings[x].SubString(y + 3, 2).ToInt();
3579  int Hrs = OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 2).ToInt();
3580  Mins -= SubMins;
3581  while(Mins < 0)
3582  {
3583  Mins += 60;
3584  Hrs--;
3585  }
3586  if(Hrs < 0)
3587  {
3588  ShowMessage("One or more times are now before 00:00, this is not permitted");
3589  Utilities->CallLogPop(1660);
3590  return;
3591  }
3592  AnsiString MinsStr = AnsiString(Mins), HrsStr = AnsiString(Hrs);
3593  if(Mins < 10)
3594  MinsStr = "0" + MinsStr;
3595  if(Hrs < 10)
3596  HrsStr = "0" + HrsStr;
3597  int StrLength = OneEntryTimetableMemo->Lines->Strings[x].Length();
3598  AnsiString NewString = OneEntryTimetableMemo->Lines->Strings[x].SubString(1, (y - 1)); // up to but not including the time
3599  NewString += HrsStr + ':' + MinsStr;
3600  NewString += OneEntryTimetableMemo->Lines->Strings[x].SubString((y + 5), (StrLength - y - 4));
3601  OneEntryTimetableMemo->Lines->Strings[x] = NewString;
3602  }
3603  }
3604  }
3605  OneEntryTimetableMemo->HideSelection = true;
3606  OneEntryTimetableMemo->SelStart = 0; // need this & next command to set cursor to the top
3607  OneEntryTimetableMemo->SelLength = 0;
3608  TimetableValidFlag = false;
3609  TimetableChangedFlag = true;
3610  TTEntryChangedFlag = true;
3612  SetLevel1Mode(92);
3613  Utilities->CallLogPop(1618);
3614  }
3615  catch(const Exception &e)
3616  {
3617  ErrorLog(55, e.Message);
3618  }
3619 }
3620 // ---------------------------------------------------------------------------
3621 
3622 void __fastcall TInterface::CopyTTEntryButtonClick(TObject *Sender)
3623 {
3624  try
3625  {
3626  TrainController->LogEvent("CopyTTEntryButtonClick");
3627  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CopyTTEntryButtonClick");
3628  if(TTCurrentEntryPtr == 0)
3629  {
3630  Utilities->CallLogPop(1636);
3631  return;
3632  }
3634  CopiedEntryFlag = true;
3635  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3636  // position changing in AllEntriesTTListBox
3638  SetLevel1Mode(93);
3639  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3640  {
3642  }
3643  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3644  {
3645  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3646  }
3647  else
3648  {
3649  AllEntriesTTListBox->TopIndex = TopPos;
3650  }
3651  Utilities->CallLogPop(1619);
3652  }
3653  catch(const Exception &e)
3654  {
3655  ErrorLog(56, e.Message);
3656  }
3657 }
3658 // ---------------------------------------------------------------------------
3659 
3660 void __fastcall TInterface::CutTTEntryButtonClick(TObject *Sender)
3661 {
3662  try
3663  {
3664  TrainController->LogEvent("CutTTEntryButtonClick");
3665  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CutTTEntryButtonClick");
3666  if(TTCurrentEntryPtr == 0) // || (*TTCurrentEntryPtr == ""))//safeguard
3667  {
3668  Utilities->CallLogPop(1674);
3669  return;
3670  }
3672  CopiedEntryFlag = true;
3673  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an erase,
3674  // so use the position in the vector
3676 // now need to rebuild all the pointers & the AllEntriesTTListBox so repeat the process from EditTimetableMenuItemClick
3677 // pick up the start time if there is one
3678  TimetableChangedFlag = true;
3679  TimetableValidFlag = false;
3680  TTEntryChangedFlag = false;
3681  TEVPtr = 0;
3683  TTFirstServicePtr = 0;
3684  TTLastServicePtr = 0; // all set to null to begin with
3685  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3686  // position changing in AllEntriesTTListBox
3687  AllEntriesTTListBox->Clear();
3689  if(TimetableEditVector.empty())
3690  {
3692  SetLevel1Mode(109);
3693  Utilities->CallLogPop(1777);
3694  return;
3695  }
3696 
3697 // reset the TTCurrentEntryPtr to the Entry before the erased one if there is one //was 'after', changed after v2.4.3
3698 // but vector pointers unreliable after an erase, so use the position in the vector
3699  if(OldVectorPos == 0)
3700  {
3702  }
3703  else
3704  {
3705  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos - 1;
3706  }
3707  if(TTCurrentEntryPtr == 0)
3708  {
3709  OneEntryTimetableMemo->Clear();
3710  }
3712  SetLevel1Mode(115);
3713  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3714  {
3716  }
3717  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3718  {
3719  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3720  }
3721  else
3722  {
3723  AllEntriesTTListBox->TopIndex = TopPos;
3724  }
3725  Utilities->CallLogPop(1676);
3726  }
3727  catch(const Exception &e)
3728  {
3729  ErrorLog(111, e.Message);
3730  }
3731 }
3732 
3733 // ---------------------------------------------------------------------------
3734 void __fastcall TInterface::PasteTTEntryButtonClick(TObject *Sender)
3735 {
3736  try
3737  {
3738  TrainController->LogEvent("PasteTTEntryButtonClick");
3739  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PasteTTEntryButtonClick");
3740  if(TTCurrentEntryPtr == 0) // || (CopiedEntryStr == "")) allow blank copies
3741  {
3742  Utilities->CallLogPop(1637);
3743  return;
3744  }
3745  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an insert
3746  TimetableEditVector.insert(TTCurrentEntryPtr + 1, CopiedEntryStr); // inserts before the indicated pointer position, i.e. immediately
3747  // after the current Entry - may be at the end
3748  TimetableChangedFlag = true;
3749  TimetableValidFlag = false;
3750  TTEntryChangedFlag = false;
3751  TEVPtr = 0;
3753  TTFirstServicePtr = 0;
3754  TTLastServicePtr = 0; // all set to null to begin with
3755  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3756  // position changing in AllEntriesTTListBox
3757  AllEntriesTTListBox->Clear();
3759  if(TimetableEditVector.empty())
3760  {
3762  SetLevel1Mode(110);
3763  Utilities->CallLogPop(1778);
3764  return;
3765  }
3766 // restore TTCurrentEntryPtr
3767  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3768  TTCurrentEntryPtr++; // advance the pointer to the pasted entry
3769 // CopiedEntryStr = "";//revert to null - no, allow multiple copies
3771  SetLevel1Mode(94);
3772  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3773  {
3775  }
3776  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3777  {
3778  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3779  }
3780  else
3781  {
3782  AllEntriesTTListBox->TopIndex = TopPos;
3783  }
3784  Utilities->CallLogPop(1620);
3785  }
3786  catch(const Exception &e)
3787  {
3788  ErrorLog(57, e.Message);
3789  }
3790 }
3791 // ---------------------------------------------------------------------------
3792 
3793 void __fastcall TInterface::DeleteTTEntryButtonClick(TObject *Sender)
3794 {
3795  try
3796  {
3797  TrainController->LogEvent("DeleteTTEntryButtonClick");
3798  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteTTEntryButtonClick");
3799  if(TTCurrentEntryPtr == 0)
3800  {
3801  Utilities->CallLogPop(1645);
3802  return;
3803  }
3804  UnicodeString MessageStr = "Are you sure this entry should be deleted?";
3805  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
3806  if(button == IDNO)
3807  {
3808  Utilities->CallLogPop(1663);
3809  return;
3810  }
3811  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an erase,
3812  // so use the position in the vector
3814 
3815 // now need to rebuild all the pointers & the AllEntriesTTListBox so repeat the process from EditTimetableMenuItemClick
3816 // pick up the start time if there is one
3817  TimetableChangedFlag = true;
3818  TimetableValidFlag = false;
3819  TTEntryChangedFlag = false;
3820  TEVPtr = 0;
3822  TTFirstServicePtr = 0;
3823  TTLastServicePtr = 0; // all set to null to begin with
3824  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3825  // position changing in AllEntriesTTListBox
3826  AllEntriesTTListBox->Clear();
3828  if(TimetableEditVector.empty())
3829  {
3831  SetLevel1Mode(111);
3832  Utilities->CallLogPop(1779);
3833  return;
3834  }
3835 // reset the TTCurrentEntryPtr to the Entry before the erased one if there is one
3836 // but vector pointers unreliable after an erase, so use the position in the vector
3837  if(OldVectorPos == 0)
3838  {
3840  }
3841  else
3842  {
3843  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos - 1;
3844  }
3845  if(TTCurrentEntryPtr == 0)
3846  {
3847  OneEntryTimetableMemo->Clear();
3848  }
3850  SetLevel1Mode(95);
3851  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3852  {
3854  }
3855  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3856  {
3857  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3858  }
3859  else
3860  {
3861  AllEntriesTTListBox->TopIndex = TopPos;
3862  }
3863  Utilities->CallLogPop(1621);
3864  }
3865  catch(const Exception &e)
3866  {
3867  ErrorLog(58, e.Message);
3868  }
3869 }
3870 // ---------------------------------------------------------------------------
3871 
3872 void __fastcall TInterface::SaveTTEntryButtonClick(TObject *Sender)
3873 {
3874  try
3875  {
3876  TrainController->LogEvent("SaveTTEntryButtonClick");
3877  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveTTEntryButtonClick");
3878 /* allow blank lines to be saved
3879  AnsiString ContentStr = OneEntryTimetableMemo->Text;
3880  if((ContentStr == "\r\n") || (ContentStr == "\n") || (ContentStr == ""))
3881  {
3882  Utilities->CallLogPop(1679);
3883  return;
3884  }
3885 */
3886  AnsiString TempStr = "";
3887  bool ActiveLine = false;
3888  if(TTCurrentEntryPtr > 0)
3889  {
3890  if(*TTCurrentEntryPtr != "")
3891  {
3893  {
3894  ActiveLine = true;
3895  // need to add commas after each line in OneEntryTimetableMemo exept the last, where have '\0'
3896  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
3897  {
3898  for(int y = 1; y <= OneEntryTimetableMemo->Lines->Strings[x].Length(); y++)
3899  {
3900  TempStr += OneEntryTimetableMemo->Lines->Strings[x][y];
3901  }
3902  if(x < (OneEntryTimetableMemo->Lines->Count - 1))
3903  {
3904  TempStr += ',';
3905  }
3906  // No need to add a '\n' as a '\0' is added automatically as a string delimiter. If add '\n' then it is treated as a blank line and
3907  // ends the timetable
3908  }
3909  // strip any excess commas from the end
3910  if(TempStr != "")
3911  {
3912  while(TempStr[TempStr.Length()] == ',')
3913  {
3914  TempStr = TempStr.SubString(1, TempStr.Length() - 1);
3915  if(TempStr == "")
3916  break;
3917  }
3918  }
3919  }
3920  }
3921  }
3922  if(!ActiveLine)
3923  {
3924  TempStr = OneEntryTimetableMemo->Text; // Note that if the entry was intended as a service but goes in as plain text because
3925  // the service & entry pointers aren't yet set, then CRLFs will be converted to commas in
3926  // CompileAllEntriesMemoAndSetPointers if it appears after the start time
3927  // and before a blank line or end of file, so the syntax check will work OK
3928  }
3929  if(AZOrderButton->Caption == AnsiString("Original Order"))
3930  {
3932  }
3933  TimetableValidFlag = false;
3934  TimetableChangedFlag = true;
3935  TTEntryChangedFlag = false;
3936  int TopPos;
3937  if(TTCurrentEntryPtr == 0)
3938  {
3940  }
3942  {
3943  (*TTCurrentEntryPtr) = TempStr;
3944  // need to reset the AllEntriesTTListBox in case the headcode has changed
3945  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an insert
3946  TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3947  // position changing in AllEntriesTTListBox
3948  AllEntriesTTListBox->Clear();
3950  if(TimetableEditVector.empty())
3951  {
3953  SetLevel1Mode(112);
3954  Utilities->CallLogPop(1780);
3955  return;
3956  }
3957  // restore TTCurrentEntryPtr
3958  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3959  }
3960  else
3961  {
3962  NewEntryInPreparationFlag = false;
3963  if(TTCurrentEntryPtr != 0)
3964  {
3965  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an insert
3966  TimetableEditVector.insert(TTCurrentEntryPtr + 1, TempStr); // inserts before the indicated pointer position, which may be at the end
3967  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3969  }
3970  else
3971  {
3972  TimetableEditVector.insert(TimetableEditVector.end(), TempStr); // inserts before the indicated pointer position
3974  }
3975  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the current position
3976  TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3977  // position changing in AllEntriesTTListBox
3978  AllEntriesTTListBox->Clear();
3980  if(TimetableEditVector.empty())
3981  {
3983  SetLevel1Mode(113);
3984  Utilities->CallLogPop(1781);
3985  return;
3986  }
3987 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
3988  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
3989  {
3991  }
3992  else
3993  {
3994  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3995  }
3996  }
3998  SetLevel1Mode(96);
3999  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4000  {
4002  }
4003  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4004  {
4005  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4006  }
4007  else
4008  {
4009  AllEntriesTTListBox->TopIndex = TopPos;
4010  }
4011  Utilities->CallLogPop(1622);
4012  }
4013  catch(const Exception &e)
4014  {
4015  ErrorLog(59, e.Message);
4016  }
4017 }
4018 // ---------------------------------------------------------------------------
4019 
4020 void __fastcall TInterface::SaveTTButtonClick(TObject *Sender)
4021 {
4022  try
4023  {
4024  TrainController->LogEvent("SaveTTButtonClick");
4025  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveTTButtonClick");
4026  if(TimetableEditVector.empty())
4027  {
4028  ShowMessage("Timetable is empty, can't save an empty timetable");
4029  Utilities->CallLogPop(1685);
4030  return;
4031  }
4032  std::ofstream TTBLFile;
4033  if(CreateEditTTFileName != "")
4034  {
4035  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary); // if text then each time sees a "\r\n" pair enters "\r\n\n" because '\n'
4036  // on its own causes "\r\n' to ne inserted, binary just enters characters as they are
4037  }
4038  else
4039  {
4040  if(SaveTTDialog->Execute())
4041  {
4042  if(SaveTTDialog->InitialDir != TPath::GetDirectoryName(SaveTTDialog->FileName))//new at v2.6.0 to retain a new directory
4043  {
4044  TimetableDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4045  SaveTTDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4046  }
4047  CreateEditTTFileName = AnsiString(SaveTTDialog->FileName);
4048  for(int x = CreateEditTTFileName.Length(); x > 0; x--)
4049  {
4050  if(CreateEditTTFileName[x] == '\\')
4051  {
4052  CreateEditTTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
4053  break;
4054  }
4055  }
4056  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary); // if text then each time sees a "\r\n" pair enters "\r\n\n" because '\n'
4057  // on its own causes "\r\n' to ne inserted, binary just enters characters as they are
4058  }
4059  else //cancelled dialog
4060  {
4062  SetLevel1Mode(137);
4063  Utilities->CallLogPop(2205);
4064  return;
4065  }
4066  }
4067  if(TTBLFile.is_open())
4068  {
4069  for(TEVPtr = TimetableEditVector.begin(); TEVPtr != TimetableEditVector.end(); TEVPtr++)
4070  {
4071  TTBLFile << (*TEVPtr).c_str() << '\0';
4072  }
4073  TimetableChangedFlag = false;
4074  TTBLFile.close();
4075  }
4076  else
4077  {
4078  ShowMessage(CreateEditTTFileName + " failed to open, ensure not already open in another application");
4079  }
4081  SetLevel1Mode(97);
4082  Utilities->CallLogPop(1623);
4083  }
4084  catch(const Exception &e)
4085  {
4086  ErrorLog(60, e.Message);
4087  }
4088 }
4089 // ---------------------------------------------------------------------------
4090 
4091 void __fastcall TInterface::SaveTTAsButtonClick(TObject *Sender)
4092 {
4093  try
4094  {
4095  TrainController->LogEvent("SaveTTAsButtonClick");
4096  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveTTAsButtonClick");
4097  if(TimetableEditVector.empty())
4098  {
4099  ShowMessage("Timetable is empty, can't save an empty timetable");
4100  Utilities->CallLogPop(1686);
4101  return;
4102  }
4103  std::ofstream TTBLFile;
4104  if(SaveTTDialog->Execute())
4105  {
4106  if(SaveTTDialog->InitialDir != TPath::GetDirectoryName(SaveTTDialog->FileName))//new at v2.6.0 to retain a new directory
4107  {
4108  TimetableDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4109  SaveTTDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4110  }
4111  CreateEditTTFileName = SaveTTDialog->FileName;
4112  for(int x = SaveTTDialog->FileName.Length(); x > 0; x--)
4113  {
4114  if(SaveTTDialog->FileName[x] == '\\')
4115  {
4116  CreateEditTTTitle = SaveTTDialog->FileName.SubString(x + 1, SaveTTDialog->FileName.Length() - x - 4);
4117  break;
4118  }
4119  }
4120  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary); // if text then each time sees a "\r\n" pair enters "\r\n\n" because '\n'
4121  // on its own causes "\r\n' to ne inserted, binary just enters characters as they are
4122  }
4123  else //cancelled dialog
4124  {
4126  SetLevel1Mode(138);
4127  Utilities->CallLogPop(2206);
4128  return;
4129  }
4130  if(TTBLFile.is_open())
4131  {
4132  for(TEVPtr = TimetableEditVector.begin(); TEVPtr != TimetableEditVector.end(); TEVPtr++)
4133  {
4134  TTBLFile << (*TEVPtr).c_str() << '\0';
4135  }
4136  TimetableChangedFlag = false;
4137  TTBLFile.close();
4138  }
4139  else
4140  {
4141  ShowMessage(CreateEditTTFileName + " failed to open, ensure not already open in another application");
4142  }
4144  SetLevel1Mode(117);
4145  Utilities->CallLogPop(1667);
4146  }
4147  catch(const Exception &e)
4148  {
4149  ErrorLog(108, e.Message);
4150  }
4151 }
4152 // ---------------------------------------------------------------------------
4153 
4154 void __fastcall TInterface::TTServiceSyntaxCheckButtonClick(TObject *Sender)
4155 {
4156  try
4157  {
4158  TrainController->LogEvent("TTServiceSyntaxCheckButtonClick");
4159  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTServiceSyntaxCheckButtonClick");
4160  int Count = 1; // anything > 0 OK as if 0 still seeking a start time
4161  bool EndOfFile = false;
4162  bool FinalCallFalse = false;
4163  bool GiveMessagesTrue = true;
4164  bool CheckLocationsExistInRailway = false;
4165  if(RlyFile)
4166  CheckLocationsExistInRailway = true;
4167 // TrainController->AnyHeadCodeValid = true; //don't fail here because of an unrestricted headcode, if no good will find when validate (dropped at v0.6b)
4168  if(TrainController->ProcessOneTimetableLine(2, Count, *TTCurrentEntryPtr, EndOfFile, FinalCallFalse, GiveMessagesTrue, CheckLocationsExistInRailway))
4169  // return true for success
4170  {
4171  ShowMessage(
4172  "The basic syntax seems OK but this check is very limited. Other aspects can only be checked by validating the whole timetable with the appropriate railway (.rly) loaded");
4173  }
4175  SetLevel1Mode(98);
4176  Utilities->CallLogPop(1624);
4177  }
4178  catch(const Exception &e)
4179  {
4180  ErrorLog(61, e.Message);
4181  }
4182 }
4183 // ---------------------------------------------------------------------------
4184 
4185 void __fastcall TInterface::ValidateTimetableButtonClick(TObject *Sender)
4186 {
4187  try
4188  {
4189  TrainController->LogEvent("ValidateTimetableButtonClick");
4190  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ValidateTimetableButtonClick");
4191  // reset all message flags, stops them being given twice new at v2.4.0
4192  TrainController->SSHigh = false;
4193  TrainController->MRSHigh = false;
4194  TrainController->MRSLow = false;
4195  TrainController->MassHigh = false;
4196  TrainController->BFHigh = false;
4197  TrainController->BFLow = false;
4198  TrainController->PwrHigh = false;
4199  TrainController->SigSHigh = false;
4200  TrainController->SigSLow = false;
4201  if(CreateEditTTFileName == "")
4202  {
4203  Utilities->CallLogPop(1664);
4204  return;
4205  }
4206  bool CheckLocationsExistInRailwayTrue = true;
4207  if(TrainController->TimetableIntegrityCheck(2, CreateEditTTFileName.c_str(), true, CheckLocationsExistInRailwayTrue)) // messages = true
4208  {
4209  Screen->Cursor = TCursor(-11); // Hourglass;
4210  std::ifstream TTBLFile(CreateEditTTFileName.c_str(), std::ios_base::binary);
4211  if(TTBLFile.is_open())
4212  {
4213  if(BuildTrainDataVectorForValidateFile(0, TTBLFile, true, CheckLocationsExistInRailwayTrue)) // messages = true
4214  {
4215  ShowMessage("Timetable integrity OK");
4216  TimetableValidFlag = true;
4217 // TrainController->TrainDataVector.clear(); keep this so can export a formatted tt
4218  };
4219  }
4220  else
4221  {
4222  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
4223  }
4224  Screen->Cursor = TCursor(-2); // Arrow
4225  } // if(TimetableIntegrityCheck
4226  else
4227  {
4228 // ShowMessage("Timetable preliminary integrity check failed"); dropped in v2.4.0 as messages given in all called functions
4229  }
4231  SetLevel1Mode(99);
4232  Utilities->CallLogPop(1625);
4233  }
4234  catch(const Exception &e)
4235  {
4236  ErrorLog(62, e.Message);
4237  }
4238 }
4239 
4240 // ---------------------------------------------------------------------------
4241 void __fastcall TInterface::MoveTTEntryUpButtonClick(TObject *Sender)
4242 {
4243  try
4244  {
4245  TrainController->LogEvent("MoveTTEntryUpButtonClick");
4246  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveTTEntryUpButtonClick");
4247  if(TTCurrentEntryPtr == 0)
4248  {
4249  Utilities->CallLogPop(1634);
4250  return;
4251  }
4252  if(TTCurrentEntryPtr < (TimetableEditVector.begin() + 1)) // shouldn't reach here but return if do
4253  {
4254  Utilities->CallLogPop(1632);
4255  return;
4256  }
4257  TEVPtr = TTCurrentEntryPtr - 1; // find earlier Entry
4258  AnsiString TempStr = *TEVPtr;
4260  *TTCurrentEntryPtr = TempStr;
4262  TimetableChangedFlag = true;
4263  TimetableValidFlag = false;
4264 
4265 // now rebuild AllEntriesTTListBox, DisplayOneTTLineInPanel will highlight it
4266  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4267  // position changing in AllEntriesTTListBox
4268  AllEntriesTTListBox->Clear();
4269  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the old position
4271 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
4272  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
4273  {
4275  }
4276  else
4277  {
4278  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
4279  }
4281  SetLevel1Mode(100);
4282  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4283  {
4285  }
4286  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4287  {
4288  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4289  }
4290  else
4291  {
4292  AllEntriesTTListBox->TopIndex = TopPos;
4293  }
4294  Utilities->CallLogPop(1626);
4295  }
4296  catch(const Exception &e)
4297  {
4298  ErrorLog(63, e.Message);
4299  }
4300 }
4301 // ---------------------------------------------------------------------------
4302 
4303 void __fastcall TInterface::MoveTTEntryDownButtonClick(TObject *Sender)
4304 {
4305  try
4306  {
4307  TrainController->LogEvent("MoveTTEntryDownButtonClick");
4308  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveTTEntryDownButtonClick");
4309  if(TTCurrentEntryPtr == 0)
4310  {
4311  Utilities->CallLogPop(1635);
4312  return;
4313  }
4314  if(TTCurrentEntryPtr >= (TimetableEditVector.end() - 1)) // shouldn't reach here but return if do
4315  {
4316  Utilities->CallLogPop(1678);
4317  return;
4318  }
4319  TEVPtr = TTCurrentEntryPtr + 1; // find later Entry
4320  AnsiString TempStr = *TEVPtr;
4322  *TTCurrentEntryPtr = TempStr;
4324  TimetableChangedFlag = true;
4325  TimetableValidFlag = false;
4326 
4327 // now rebuild AllEntriesTTListBox, DisplayOneTTLineInPanel will highlight it
4328  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4329  // position changing in AllEntriesTTListBox
4330  AllEntriesTTListBox->Clear();
4331  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the old position
4333 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
4334  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
4335  {
4337  }
4338  else
4339  {
4340  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
4341  }
4343  SetLevel1Mode(101);
4344  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4345  {
4347  }
4348  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4349  {
4350  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4351  }
4352  else
4353  {
4354  AllEntriesTTListBox->TopIndex = TopPos;
4355  }
4356  Utilities->CallLogPop(1627);
4357  }
4358  catch(const Exception &e)
4359  {
4360  ErrorLog(64, e.Message);
4361  }
4362 }
4363 
4364 // ---------------------------------------------------------------------------
4365 void __fastcall TInterface::CancelTTEntryButtonClick(TObject *Sender)
4366 {
4367  try
4368  {
4369  TrainController->LogEvent("CancelTTActionButtonClick");
4370  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CancelTTActionButtonClick");
4371  TTEntryChangedFlag = false;
4373  {
4374  NewEntryInPreparationFlag = false;
4375  OneEntryTimetableMemo->Clear();
4376  }
4377  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4378  // position changing in AllEntriesTTListBox
4380  SetLevel1Mode(102);
4381  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4382  {
4384  }
4385  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4386  {
4387  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4388  }
4389  else
4390  {
4391  AllEntriesTTListBox->TopIndex = TopPos;
4392  }
4393  Utilities->CallLogPop(1630);
4394  }
4395  catch(const Exception &e)
4396  {
4397  ErrorLog(102, e.Message);
4398  }
4399 }
4400 
4401 // ---------------------------------------------------------------------------
4402 void __fastcall TInterface::RestoreTTButtonClick(TObject *Sender)
4403 {
4404  try
4405  {
4406  TrainController->LogEvent("RestoreTTButtonClick");
4407  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RestoreTTButtonClick");
4409  {
4410  UnicodeString MessageStr = "All changes to the timetable will be lost - proceed?";
4411  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
4412  if(button == IDNO)
4413  {
4414  Utilities->CallLogPop(1651);
4415  return;
4416  }
4417  }
4418 
4419  // repeat from EditTimetableMenuItemClick, but no need to check for non-ascii characters
4420  // open in binary mode so the "\r\n" pairs stay as they are rather than being entered as '\n'
4421  std::ifstream TTBLFile(CreateEditTTFileName.c_str(), std::ios_base::binary);
4422  if(TTBLFile.is_open())
4423  {
4424  TimetableChangedFlag = false;
4425  TimetableValidFlag = false;
4426  TTEntryChangedFlag = false;
4427  NewEntryInPreparationFlag = false;
4428  CopiedEntryFlag = false;
4429  CopiedEntryStr = "";
4430  TimetableEditVector.clear();
4431  OneEntryTimetableMemo->Clear();
4432  AllEntriesTTListBox->Clear();
4433  TTStartTimeBox->Text = "";
4434  AddSubMinsBox->Text = "";
4435  TEVPtr = 0;
4437  TTFirstServicePtr = 0;
4438  TTLastServicePtr = 0; // all set to null to begin with
4439  char *TimetableEntryString = new char[10000];
4440  while(true)
4441  {
4442  TTBLFile.getline(TimetableEntryString, 10000, '\0'); // pick up the entire AnsiString, including any embedded newlines
4443  if(TTBLFile.eof() && (TimetableEntryString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
4444  { // may still have eof even if read a line, and
4445  // if so need to process it
4446  break;
4447  }
4448  AnsiString OneLine(TimetableEntryString);
4449  TimetableEditVector.push_back(OneLine);
4450  }
4451  TTBLFile.close();
4452  delete TimetableEntryString;
4453  // here with TimetableEditVector compiled
4454  }
4455  else
4456  {
4457  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
4458  Utilities->CallLogPop(1655);
4459  return;
4460  }
4461 
4463  if(TimetableEditVector.empty())
4464  {
4466  SetLevel1Mode(114);
4467  Utilities->CallLogPop(1782);
4468  return;
4469  }
4470 // all now set where can be
4472 // end of repeat from EditTimetableMenuItemClick
4473 
4475  SetLevel1Mode(104);
4476  Utilities->CallLogPop(1652);
4477  }
4478  catch(const Exception &e)
4479  {
4480  ErrorLog(104, e.Message);
4481  }
4482 }
4483 
4484 // ---------------------------------------------------------------------------
4485 void __fastcall TInterface::ExportTTButtonClick(TObject *Sender)
4486 {
4487  try
4488  {
4489  TrainController->LogEvent("ExportTTButtonClick");
4490  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExportTTButtonClick");
4491  if(!DirectoryExists(CurDir + "\\" + FORMATTEDTT_DIR_NAME))
4492  {
4493  ShowMessage("Failed to find folder " + FORMATTEDTT_DIR_NAME + " in the folder where 'railway.exe' resides. Timetable can't be exported");
4494  Utilities->CallLogPop(1698);
4495  return;
4496  }
4497 // Screen->Cursor = TCursor(-11); // Hourglass; - no good setting here as it's reset by ShowMessage in CreateFormattedTimetable. It's set there after
4498 // the message instead, but reset here afterwards
4499  AnsiString TTTitle;
4501  {
4502  for(int x = CreateEditTTFileName.Length(); x > 0; x--) // first need to strip out the timetable title from the full name
4503  {
4504  if(CreateEditTTFileName[x] == '\\')
4505  {
4506  TTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
4507  break;
4508  }
4509  }
4511  }
4512  Screen->Cursor = TCursor(-2); // Arrow - reset after above function returns
4514  SetLevel1Mode(116);
4515  Utilities->CallLogPop(1662);
4516  }
4517  catch(const Exception &e)
4518  {
4519  ErrorLog(107, e.Message);
4520  }
4521 }
4522 
4523 // ---------------------------------------------------------------------------
4524 void __fastcall TInterface::TTTextButtonClick(TObject *Sender)
4525 {
4526  try
4527  {
4528  TrainController->LogEvent("TTTextButtonClick");
4529  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTTextButtonClick");
4530 /*
4531  if(TTStartTimePtr == 0)
4532  {
4533  OneEntryTimetableMemo->Clear();
4534  TTStartTimeBox->SetFocus();
4535  Utilities->CallLogPop(1673);
4536  return;
4537  }
4538 */
4539  int SelPos = OneEntryTimetableMemo->SelStart;
4540  AnsiString FirstPart = OneEntryTimetableMemo->Text.SubString(1, SelPos);
4541  AnsiString LastPart = OneEntryTimetableMemo->Text.SubString(SelPos + 1, OneEntryTimetableMemo->Text.Length() - SelPos);
4542  OneEntryTimetableMemo->Text = FirstPart + ((TButton*)Sender)->Caption + LastPart;
4543  OneEntryTimetableMemo->SelStart = SelPos + ((TButton*)Sender)->Caption.Length();
4544  TTEntryChangedFlag = true;
4545  OneEntryTimetableMemo->SetFocus();
4547  SetLevel1Mode(119);
4548  Utilities->CallLogPop(1672);
4549  }
4550  catch(const Exception &e)
4551  {
4552  ErrorLog(110, e.Message);
4553  }
4554 }
4555 
4556 // ---------------------------------------------------------------------------
4557 void __fastcall TInterface::ExitTTModeButtonClick(TObject *Sender)
4558 {
4559  try
4560  {
4561  TrainController->LogEvent("ExitTTCreateEditButtonClick");
4562  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitTTCreateEditButtonClick");
4564  {
4565  UnicodeString MessageStr = "The timetable has changed.\n\nAre you sure you want to exit without saving it?";
4566  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
4567  if(button == IDNO)
4568  {
4569  Utilities->CallLogPop(1603);
4570  return;
4571  }
4572  }
4573  TimetableChangedFlag = false;
4574  CreateEditTTFileName = ""; // set to null to allow a check during error file saving, if not null save the tt being edited to the file
4575  // added for Beta v0.2b
4576  CreateEditTTTitle = ""; // as above
4577  ConflictPanel->Visible = false;
4578  Level1Mode = BaseMode;
4579  SetLevel1Mode(84);
4580  Utilities->CallLogPop(1606);
4581  }
4582  catch(const Exception &e)
4583  {
4584  ErrorLog(49, e.Message);
4585  }
4586 }
4587 
4588 // ---------------------------------------------------------------------------
4589 void __fastcall TInterface::LocationNameComboBoxClick(TObject *Sender)
4590 {
4591  try
4592  {
4593  TrainController->LogEvent("LocationNameComboBoxClick");
4594  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameComboBoxClick");
4595  if(TTStartTimePtr != 0)
4596  {
4597  LocationNameComboBox->SelectAll();
4598  int SelPos = OneEntryTimetableMemo->SelStart;
4599  AnsiString FirstPart = OneEntryTimetableMemo->Text.SubString(1, SelPos);
4600  AnsiString LastPart = OneEntryTimetableMemo->Text.SubString(SelPos + 1, OneEntryTimetableMemo->Text.Length() - SelPos);
4601  OneEntryTimetableMemo->Text = FirstPart + LocationNameComboBox->SelText + LastPart;
4602  OneEntryTimetableMemo->SelStart = SelPos + LocationNameComboBox->SelText.Length();
4603  TTEntryChangedFlag = true;
4604  OneEntryTimetableMemo->SetFocus();
4606  SetLevel1Mode(118);
4607  }
4608  Utilities->CallLogPop(1669);
4609  }
4610  catch(const Exception &e)
4611  {
4612  ErrorLog(109, e.Message);
4613  }
4614 }
4615 
4616 // ---------------------------------------------------------------------------
4617 void __fastcall TInterface::OneEntryTimetableMemoKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
4618 {
4619  try
4620  {
4621 // TrainController->LogEvent("OneEntryTimetableMemoKeyUp"); drop this - too many entries
4622  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OneEntryTimetableMemoKeyUp");
4624  {
4625  Utilities->CallLogPop(1716);
4626  return;
4627  }
4628  TimetableChangedFlag = true;
4629  TTEntryChangedFlag = true;
4630  TimetableValidFlag = false;
4632  SetLevel1Mode(127);
4633  Utilities->CallLogPop(1629);
4634  }
4635  catch(const Exception &e)
4636  {
4637  ErrorLog(66, e.Message);
4638  }
4639 }
4640 
4641 // ---------------------------------------------------------------------------
4642 void __fastcall TInterface::AddSubMinsBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
4643 {
4644 // forces a recheck for whether addmins/submins buttons should be enabled
4645  try
4646  {
4647  TrainController->LogEvent("AddSubMinsBoxKeyUp");
4648  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddSubMinsBoxKeyUp");
4650  SetLevel1Mode(108);
4651  Utilities->CallLogPop(1658);
4652  }
4653  catch(const Exception &e)
4654  {
4655  ErrorLog(106, e.Message);
4656  }
4657 }
4658 
4659 // ---------------------------------------------------------------------------
4660 void __fastcall TInterface::LocationNameComboBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
4661 {
4662  try
4663  {
4664  TrainController->LogEvent("LocationNameComboBoxKeyUp");
4665  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameComboBoxKeyUp");
4666  if(!Track->LocationNameMultiMap.empty())
4667  {
4668  LocationNameComboBox->Text = "Location names";
4669  }
4670  else
4671  {
4672  LocationNameComboBox->Text = "No locations (listed when a railway with names is loaded)";
4673  }
4674  Utilities->CallLogPop(1677);
4675  }
4676  catch(const Exception &e)
4677  {
4678  ErrorLog(112, e.Message);
4679  }
4680 }
4681 
4682 // ---------------------------------------------------------------------------
4683 
4684 void __fastcall TInterface::AllEntriesTTListBoxMouseUp(TObject *Sender, TMouseButton Button,
4685  TShiftState Shift, int X, int Y)
4686 {
4687 // Select the item pointed to unless a 'save entry' is pending in which case ignore
4688  try
4689  {
4690  TrainController->LogEvent("AllEntriesTTListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4691  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AllEntriesTTListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4692  if((TTCurrentEntryPtr == 0) || TimetableEditVector.empty())
4693  {
4694  Utilities->CallLogPop(1687);
4695  return;
4696  }
4697  if(TTEntryChangedFlag || NewEntryInPreparationFlag) // if a save/cancel pending don't permit anything else
4698  {
4699  Utilities->CallLogPop(1688);
4700  return;
4701  }
4702  // find item required - 13 pixels per line of text
4703  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4704  // position changing in AllEntriesTTListBox
4705  if((TopPos + (Y / 13)) >= AllEntriesTTListBox->Items->Count)
4706  {
4708  }
4709  else
4710  {
4711  TTCurrentEntryPtr = TimetableEditVector.begin() + (Y / 13) + TopPos;
4712  }
4713  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the old position
4715 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
4716  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
4717  {
4719  }
4720  else
4721  {
4722  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
4723  }
4725  SetLevel1Mode(120);
4726  AllEntriesTTListBox->TopIndex = TopPos; // reset it after SetLevel1Mode to prevent the scroll position changing
4727  Utilities->CallLogPop(1648);
4728  }
4729  catch(const Exception &e)
4730  {
4731  ErrorLog(103, e.Message);
4732  }
4733 }
4734 
4735 // ---------------------------------------------------------------------------
4736 
4737 void __fastcall TInterface::OAListBoxMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
4738 {
4739 // Mouseup rather than Mousedown so shows floating label when over train
4740  try
4741  {
4742  TrainController->LogEvent("OAListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4743  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OAListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4744  if(Track->RouteFlashFlag || Track->PointFlashFlag) // no action
4745  {
4746  Utilities->CallLogPop(2087);
4747  return;
4748  }
4750  {
4751  Utilities->CallLogPop(2088);
4752  return;
4753  }
4755  // find item required - 13 pixels per line of text
4756  int TopPos = OAListBox->TopIndex;
4757  int OAIndex;
4758  if((TopPos + (Y / 13)) >= OAListBox->Items->Count) // if click beyond end of list ignore
4759  {
4760  Utilities->CallLogPop(2089);
4761  return;
4762  }
4763  else
4764  {
4765  OACurrentEntryPtr = TrainController->OpTimeToActMultiMap.begin();
4766  std::advance(OACurrentEntryPtr, ((Y / 13) + TopPos));
4767  }
4768  int HPos;
4769  int VPos;
4770  int TrackVectorPosition;
4771  int TrainIDorTVPos = OACurrentEntryPtr->second.second;
4772  if(TrainIDorTVPos >= 0) // running train, so value is the TrainID
4773  {
4774  if(TrainController->TrainExistsAtIdent(0, TrainIDorTVPos)) // added at v2.4.0 in case train removed but still in OA list as not updated yet
4775  // see LiWinDom error report on Discord 23/04/20. Also needed for click OAListBox before any trains show,
4776  // as notified by Rokas Serys by email on 16/05/20
4777  {
4778  TrackVectorPosition = TrainController->TrainVectorAtIdent(43, TrainIDorTVPos).LeadElement;
4779  }
4780  else
4781  {
4782  Utilities->CallLogPop(2155); // if not there then ignore
4783  return;
4784  }
4785  }
4786  else // train to enter at a continuation, so value is -TVPos of continuation - 1
4787  {
4788  TrackVectorPosition = -(TrainIDorTVPos + 1);
4789  }
4790  HPos = (Track->TrackElementAt(926, TrackVectorPosition).HLoc * 16);
4791  VPos = (Track->TrackElementAt(927, TrackVectorPosition).VLoc * 16);
4792  // now want to set the offsets to display HPos & VPos in the centre of the screen
4793  Display->DisplayOffsetH = (HPos - MainScreen->Width / 2) / 16; // ScreenPosH = HPos - (DisplayOffsetH * 16)
4794  Display->DisplayOffsetV = (VPos - MainScreen->Height / 2) / 16;
4795  int ScreenPosH = HPos - (Display->DisplayOffsetH * 16);
4796  int ScreenPosV = VPos - (Display->DisplayOffsetV * 16);
4797  if(Display->ZoomOutFlag) // panel displays in either zoom mode
4798  {
4799  Display->ZoomOutFlag = false;
4801  }
4802  ClearandRebuildRailway(72); // if was zoomed out this displays the track because until ZoomOutFlag reset PlotOutput plots nothing
4803  TPoint MainScreenPoint(ScreenPosH + 8, ScreenPosV + 8); // new v2.2.0 add 8 to centre pointer in element
4804  TPoint CursPos = MainScreen->ClientToScreen(MainScreenPoint); // accurate funtion to convert from local to global co-ordinates
4805  Mouse->CursorPos = CursPos;
4806  Utilities->CallLogPop(2090);
4807  }
4808  catch(const Exception &e)
4809  {
4810  ErrorLog(200, e.Message);
4811  }
4812 }
4813 
4814 // ---------------------------------------------------------------------------
4815 
4817 {
4818  enum
4819  {
4820  PreStartTime, ActiveSegment, PostEnd} Segment;
4821  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CompileAllEntriesMemoAndSetPointers");
4822  AllEntriesTTListBox->Clear();
4823  TEVPtr = 0;
4824  TTStartTimePtr = 0;
4825  TTFirstServicePtr = 0;
4826  TTLastServicePtr = 0; // all set to null to begin with
4827  if(TimetableEditVector.empty())
4828  {
4829  TTCurrentEntryPtr = 0;
4830  Utilities->CallLogPop(1681);
4831  return;
4832  }
4833  Segment = PreStartTime;
4834  for(TEVPtr = TimetableEditVector.begin(); TEVPtr != TimetableEditVector.end(); TEVPtr++)
4835  {
4836  if(Segment == PreStartTime) // looking for the start time
4837  {
4838  TDateTime TempTime; // dummy
4839  if(TrainController->CheckTimeValidity(33, *TEVPtr, TempTime))
4840  {
4841  TTStartTimePtr = TEVPtr; // TTStartTimeBox text set in TTHandler
4842  AllEntriesTTListBox->Items->Add("START " + (*TEVPtr).SubString(1, 5));
4843  Segment = ActiveSegment;
4844  continue;
4845  }
4846  else
4847  {
4848  if(*TEVPtr == "")
4849  {
4850  AllEntriesTTListBox->Items->Add("- Blank");
4851  }
4852  else
4853  {
4854  AnsiString CurrentStr = *TEVPtr;
4855  if(CurrentStr != "") // strip any non alphanumeric characters (specifically \r or \n)
4856  {
4857  CurrentStr = CurrentStr.SubString(1, 10); // limit length for LH window
4858  for(int x = 1; x < CurrentStr.Length(); x++)
4859  {
4860  if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
4861  {
4862  CurrentStr = CurrentStr.SubString(1, (x - 1));
4863  }
4864  }
4865  }
4866  AllEntriesTTListBox->Items->Add("- " + CurrentStr);
4867  }
4868  continue;
4869  }
4870  }
4871  if(Segment == ActiveSegment)
4872  {
4873  if(*TEVPtr != "")
4874  {
4875  if((*TEVPtr)[1] != '*')
4876  {
4878  ConvertCRLFsToCommas(0, *TEVPtr); // This needed because an entry intended as a service might have skipped the conversion in
4879  // SaveTTEntryButtonClick - see comment in that function
4880  if(TTFirstServicePtr == 0)
4881  {
4883  }
4885  }
4886  AnsiString Entry = *TEVPtr;
4887  if(Entry[1] == '*')
4888  Entry = "Comment";
4889  else
4890  {
4891  int SCPos = Entry.Pos(';'); // semicolon
4892  int CPos = Entry.Pos(','); // comma
4893  // 5 possibilities: no comma & no semicolon - just text - enter 1st 12 characters
4894  // both, comma before semicolon, i.e text on its own line, semicolon on next line - e.g. service headcode but no
4895  // description - enter the text up to the comma
4896  // both, semicolon before comma, normal - enter text up to the semicolon
4897  // comma & no semicolon, one or more lines of text without any semicolons - enter the text up to the comma
4898  // semicolon & no comma - enter text up to the semicolon
4899  if((CPos == 0) && (SCPos == 0))
4900  {
4901  Entry = Entry.SubString(1, 12);
4902  }
4903  else if((CPos > 0) && (SCPos > 0) && (CPos < SCPos))
4904  {
4905  Entry = Entry.SubString(1, CPos - 1);
4906  }
4907  else if((CPos > 0) && (SCPos > 0) && (CPos > SCPos))
4908  {
4909  Entry = Entry.SubString(1, SCPos - 1);
4910  }
4911  else if((CPos > 0) && (SCPos == 0))
4912  {
4913  Entry = Entry.SubString(1, CPos - 1);
4914  }
4915  else
4916  {
4917  Entry = Entry.SubString(1, SCPos - 1);
4918  }
4919  }
4920  AllEntriesTTListBox->Items->Add(Entry);
4921  continue;
4922  }
4923  else
4924  {
4925  Segment = PostEnd;
4926  AllEntriesTTListBox->Items->Add("END (Blank)");
4927  continue;
4928  }
4929  }
4930  if(Segment == PostEnd)
4931  {
4932  if(*TEVPtr == "")
4933  {
4934  AllEntriesTTListBox->Items->Add("+ Blank");
4935  }
4936  else
4937  {
4938  AnsiString CurrentStr = *TEVPtr;
4939  if(CurrentStr != "") // strip any non alphanumeric characters (specifically \r or \n)
4940  {
4941  CurrentStr = CurrentStr.SubString(1, 10);
4942  for(int x = 1; x < CurrentStr.Length(); x++)
4943  {
4944  if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
4945  {
4946  CurrentStr = CurrentStr.SubString(1, (x - 1));
4947  }
4948  }
4949  }
4950  AllEntriesTTListBox->Items->Add("+ " + CurrentStr);
4951  }
4952  continue;
4953  }
4954  }
4955  if(TTStartTimePtr == 0)
4956  {
4957  TTStartTimeBox->Text = "";
4958  }
4959  TTCurrentEntryPtr = TTLastServicePtr; // may well be reset outside this function but need to ensure that it has a valid value on exit, even if it's null
4960  Utilities->CallLogPop(1680);
4961 }
4962 // ---------------------------------------------------------------------------
4963 
4964 void __fastcall TInterface::AZOrderButtonClick(TObject *Sender)
4965 {
4966  try
4967  {
4968  if(TimetableEditVector.empty())
4969  {
4970  return; // should be able to access this if it is but keep in for safety
4971  }
4972  TrainController->LogEvent("AZOrderClick");
4973  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AZOrderClick");
4974  if(AZOrderButton->Caption == AnsiString("A-Z Order"))
4975  {
4976  TTEVPtr SortStart, SortEnd;
4977  UnicodeString MessageStr =
4978  "If you wish to preserve the original order don't make any changes whilst in alphabetical order.\n\nIn that case use alphabetical order to find the service required, click it to display it, then revert to the original order where the same service will be displayed and can be changed.";
4979  Application->MessageBox(MessageStr.c_str(), L"Please Note:", MB_OK | MB_ICONWARNING);
4982  SortStart = TimetableEditVector.begin(); // if no start time set sort from beginning
4983  if(TTFirstServicePtr != NULL)
4984  {
4985  SortStart = TTFirstServicePtr;
4986  }
4987  SortEnd = TimetableEditVector.end(); // if no last service set sort to end
4988  if(TTLastServicePtr != NULL)
4989  {
4990  SortEnd = TTLastServicePtr + 1;
4991  }
4992  std::sort(SortStart, SortEnd);
4994  bool CurrentEntryChanged = false;
4995  for(TTimetableEditVector::iterator x = TimetableEditVector.begin(); x < TimetableEditVector.end(); x++)
4996  {
4997  if(TTSelectedEntry == *x)
4998  {
4999  TTCurrentEntryPtr = x;
5000  CurrentEntryChanged = true;
5001  }
5002  }
5003  if(!CurrentEntryChanged)
5004  {
5006  }
5007  AZOrderButton->Caption = AnsiString("Original Order");
5008  AZOrderButton->Hint = AnsiString("Arrange services in original order Toggle with Shift+ Z");
5009  }
5010  else
5011  {
5013  {
5014  UnicodeString MessageStr =
5015  "Reverting to the original order will discard any changes made whilst in alphabetical order.\n\nTo preserve the changes click 'No', then save the timetable or use 'save as' if you wish to keep the original timetable.\n\nDo you wish to proceed?";
5016  int button = Application->MessageBox(MessageStr.c_str(), L"Warning!", MB_YESNO | MB_ICONWARNING);
5017  if(button == IDNO)
5018  {
5019  TimetableChangedFlag = true;
5020  TimetableValidFlag = false;
5022  SetLevel1Mode(135);
5023  Utilities->CallLogPop(2166);
5024  return;
5025  }
5026  }
5030  bool CurrentEntryChanged = false;
5031  for(TTimetableEditVector::iterator x = TimetableEditVector.begin(); x < TimetableEditVector.end(); x++)
5032  {
5033  if(TTSelectedEntry == *x)
5034  {
5035  TTCurrentEntryPtr = x;
5036  CurrentEntryChanged = true;
5037  }
5038  }
5039  if(!CurrentEntryChanged)
5040  {
5042  }
5043  AZOrderButton->Caption = AnsiString("A-Z Order");
5044  AZOrderButton->Hint = AnsiString("Arrange services in alphabetical order Toggle with Shift+ Z");
5045  }
5046  TimetableChangedFlag = true;
5047  TimetableValidFlag = false;
5050  SetLevel1Mode(136);
5051  Utilities->CallLogPop(2165);
5052  }
5053  catch(const Exception &e)
5054  {
5055  ErrorLog(211, e.Message);
5056  }
5057 }
5058 
5059 // ---------------------------------------------------------------------------
5060 
5061 void TInterface::ConvertCRLFsToCommas(int Caller, AnsiString &ConvStr)
5062 {
5063  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ConvertCRLFsToCommas," + ConvStr);
5064  AnsiString OutStr = "";
5065  int x = 1; // AnsiString arrays start at 1
5066 
5067  while(x < ConvStr.Length()) // skip the last character as looking for CRLF pairs, i.e. '\r' followed by '\n'
5068  {
5069  if((ConvStr[x] == '\r') && (ConvStr[x + 1] == '\n'))
5070  {
5071  OutStr += ',';
5072  x++;
5073  x++;
5074  }
5075  else
5076  {
5077  OutStr += ConvStr[x];
5078  x++;
5079  }
5080  }
5081  if(x == ConvStr.Length())
5082  OutStr += ConvStr[x]; // add the last character
5083 
5084 // strip any excess commas from the end
5085  if(OutStr != "")
5086  {
5087  while(OutStr[OutStr.Length()] == ',')
5088  {
5089  OutStr = OutStr.SubString(1, OutStr.Length() - 1);
5090  if(OutStr == "")
5091  break; // if consisted of just commas then without this would fail on range error when becomes a null string
5092  }
5093  }
5094  ConvStr = OutStr;
5095  if(ConvStr == "")
5096  ConvStr = ','; // don't return a null or will fail, OK to return a comma on its own as will be ignored during ProcessOneTimetableLine
5097  // when AllCommas will be true
5098  Utilities->CallLogPop(1846);
5099 }
5100 
5101 // ---------------------------------------------------------------------------
5102 
5104 {
5105 /* CreateEditTTFileName set if a TT file loaded (even if empty), the pointers TTStartTimePtr, TTFirstServicePtr, TTLastServicePtr provide
5106  relevant information - if null then not set. TTCurrentEntryPtr is set to the Entry to be displayed or null if there's no start time or no
5107  entries
5108 */
5109  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TimetableHandler");
5110  PreviousTTEntryButton->Enabled = false;
5111  NextTTEntryButton->Enabled = false;
5112  AddMinsButton->Enabled = false;
5113  SubMinsButton->Enabled = false;
5114  CopyTTEntryButton->Enabled = false;
5115  CutTTEntryButton->Enabled = false;
5116  PasteTTEntryButton->Enabled = false;
5117  DeleteTTEntryButton->Enabled = false;
5118  SaveTTEntryButton->Enabled = false;
5119  SaveTTButton->Enabled = false;
5120  SaveTTAsButton->Enabled = false;
5121  ValidateTimetableButton->Enabled = false;
5122  AZOrderButton->Enabled = false;
5123  TTServiceSyntaxCheckButton->Enabled = false;
5124  NewTTEntryButton->Enabled = false;
5125  MoveTTEntryUpButton->Enabled = false;
5126  MoveTTEntryDownButton->Enabled = false;
5127  CancelTTEntryButton->Enabled = false;
5128  RestoreTTButton->Enabled = false;
5129  ExportTTButton->Enabled = false;
5130  ConflictAnalysisButton->Enabled = false;
5131  ExitTTModeButton->Enabled = true;
5132 
5134  {
5135  AZOrderButton->Enabled = true;
5136  }
5137 
5139  TimetableValidFlag = false; // should always be the case anyway but include here to be sure
5140 
5141  if(CreateEditTTFileName == "")
5142  {
5143  TimetableNameLabel->Caption = "Creating new timetable: not yet saved";
5144  }
5145  else
5146  {
5147  TimetableNameLabel->Caption = "Editing timetable: " + CreateEditTTTitle;
5148  }
5149 
5150  if(TTStartTimePtr != 0) // Null means start time not yet set
5151  {
5152  TTStartTimeBox->Text = (*TTStartTimePtr).SubString(1, 5); // 1st 5 chars = time if validity check OK
5153  }
5154 // start time now set & displayed
5155 
5157  {
5158  InfoPanel->Visible = true;
5159  InfoPanel->Caption = "Select option or change entry";
5160  if(RailwayTitle != "")
5161  {
5162  ShowHideTTButton->Enabled = true;
5163  }
5164  else
5165  {
5166  ShowHideTTButton->Enabled = false;
5167  }
5168  ExitTTModeButton->Enabled = true;
5169  AllEntriesTTListBox->Enabled = true;
5170  AnsiString AnsiAddSubText(AddSubMinsBox->Text);
5171  if((AnsiAddSubText != "") && AreAnyTimesInCurrentEntry())
5172  {
5173  bool ValidFlag = true;
5174  for(int x = 1; x <= AnsiAddSubText.Length(); x++)
5175  {
5176  if((AnsiAddSubText[x] > '9') || (AnsiAddSubText[x] < '0'))
5177  {
5178  ValidFlag = false;
5179  break;
5180  }
5181  }
5182  if(ValidFlag)
5183  {
5184  if(AnsiAddSubText.ToInt() != 0)
5185  {
5186  AddMinsButton->Enabled = true;
5187  SubMinsButton->Enabled = true;
5188  }
5189  }
5190  }
5192  {
5193  RestoreTTButton->Enabled = true;
5194  }
5196  { // Need !TimetableChangedFlag because the changed TT must be saved before validation - it's the TT file that is checked
5197  // so if it is changed but not saved, the 'correct' file will check OK but the changed TT may well not be valid
5198  ValidateTimetableButton->Enabled = true;
5199  }
5201  {
5202  ExportTTButton->Enabled = true;
5203  ConflictAnalysisButton->Enabled = true;
5204  }
5205  if(TTCurrentEntryPtr != 0)
5206  {
5207  CopyTTEntryButton->Enabled = true;
5208  CutTTEntryButton->Enabled = true;
5209  DeleteTTEntryButton->Enabled = true;
5210  }
5211  if((TimetableChangedFlag) && !TimetableEditVector.empty())
5212  {
5213  SaveTTButton->Enabled = true;
5214  }
5215  if(!TimetableEditVector.empty())
5216  {
5217  SaveTTAsButton->Enabled = true;
5218  }
5220  {
5221  NewTTEntryButton->Enabled = true;
5222  }
5223  if((TTCurrentEntryPtr > 0) && !TimetableEditVector.empty())
5224  {
5225  if((TimetableEditVector.end() - 1) > TTCurrentEntryPtr)
5226  {
5227  NextTTEntryButton->Enabled = true;
5228  MoveTTEntryDownButton->Enabled = true;
5229  }
5231  {
5232  PreviousTTEntryButton->Enabled = true;
5233  MoveTTEntryUpButton->Enabled = true;
5234  }
5235  }
5236  if(TTCurrentEntryPtr > 0)
5237  {
5238  if(*TTCurrentEntryPtr != "")
5239  {
5241  {
5242  TTServiceSyntaxCheckButton->Enabled = true;
5243  }
5244  }
5245  }
5246  if(CopiedEntryFlag)
5247  {
5248  PasteTTEntryButton->Enabled = true;
5249  }
5250  OneEntryTimetableMemo->Clear(); // don't clear if Entry changed
5251  if(TTCurrentEntryPtr > 0)
5252  {
5253 // if(*TTCurrentEntryPtr != "") leave this out or fails to highlight blank line entries
5255  {
5256  bool ServiceEntry = true;
5257  DisplayOneTTLineInPanel(0, *TTCurrentEntryPtr, ServiceEntry);
5258  }
5259  else
5260  {
5261  bool ServiceEntry = false;
5262  DisplayOneTTLineInPanel(1, *TTCurrentEntryPtr, ServiceEntry);
5263  }
5264  }
5265  }
5266  else
5267  {
5268  CancelTTEntryButton->Enabled = true;
5269  SaveTTEntryButton->Enabled = true;
5270  ShowHideTTButton->Enabled = false;
5271  ExitTTModeButton->Enabled = false;
5272  AllEntriesTTListBox->Enabled = false; // to stop entries being selected
5273  InfoPanel->Caption = "Add or change entry then save it, or cancel";
5274  InfoPanel->Visible = true;
5275  }
5276  Utilities->CallLogPop(1600);
5277 }
5278 
5279 // ---------------------------------------------------------------------------
5280 void TInterface::DisplayOneTTLineInPanel(int Caller, AnsiString Data, bool ServiceEntry)
5281 {
5282  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",DisplayOneTTLineInPanel," + Data + ", " +
5283  AnsiString((short)ServiceEntry));
5284  OneEntryTimetableMemo->Clear();
5285  if(ServiceEntry)
5286  {
5287  TrainController->StripSpaces(1, Data);
5288  while(true)
5289  {
5290  int CommaPos = Data.Pos(',');
5291  if((CommaPos == 0) && (Data != ""))
5292  {
5293  CommaPos = Data.Length() + 1;
5294  }
5295  OneEntryTimetableMemo->Lines->Add(Data.SubString(1, CommaPos - 1));
5296  if(Data.Length() <= CommaPos)
5297  break;
5298  Data = Data.SubString(CommaPos + 1, Data.Length() - CommaPos);
5299  }
5300  }
5301  else
5302  {
5303  OneEntryTimetableMemo->Text = Data;
5304  }
5305  int TotalLines = OneEntryTimetableMemo->Lines->Count; // remove excess lines at bottom
5306 
5307  while((OneEntryTimetableMemo->Lines->Strings[TotalLines - 1] == "") || (OneEntryTimetableMemo->Lines->Strings[TotalLines - 1] == "\r\n"))
5308  {
5309  OneEntryTimetableMemo->Lines->Delete(TotalLines - 1);
5310  TotalLines--;
5311  if(TotalLines < 1)
5312  break;
5313  }
5314  OneEntryTimetableMemo->HideSelection = true;
5315  OneEntryTimetableMemo->SelStart = 0; // need this & next command to set cursor to the top
5316  OneEntryTimetableMemo->SelLength = 0;
5318  Utilities->CallLogPop(1602);
5319 }
5320 // ---------------------------------------------------------------------------
5321 
5323 {
5324  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",HighlightOneEntryInAllEntriesTTListBox," + AnsiString(Position));
5325  if(TimetableEditVector.empty() || (AllEntriesTTListBox->Items->Count == 0))
5326  {
5327  HighlightPanel->Top = 32;
5328  HighlightPanel->Caption = "";
5329  HighlightPanel->Width = 100;
5330  HighlightPanel->Visible = false;
5331  }
5332  else
5333  {
5334  AnsiString CurrentStr = AllEntriesTTListBox->Items->Strings[Position];
5335  if(CurrentStr != "") // strip any non alphanumeric characters (specifically \r or \n)
5336  {
5337  for(int x = 1; x < CurrentStr.Length(); x++)
5338  {
5339  if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
5340  {
5341  CurrentStr = CurrentStr.SubString(1, (x - 1));
5342  }
5343  }
5344  }
5345  HighlightPanel->Top = 32 + (Position * 13) - (AllEntriesTTListBox->TopIndex * 13);
5346  if(HighlightPanel->Top < 32)
5347  HighlightPanel->Visible = false;
5348  else
5349  HighlightPanel->Visible = true; // doesn't matter if goes off the bottom as it becomes invisible as then it's off its parent panel
5350  HighlightPanel->Caption = CurrentStr;
5351  if(AllEntriesTTListBox->Items->Count > 47) //because the scrollbar will be present
5352  HighlightPanel->Width = 82;
5353  else
5354  HighlightPanel->Width = 100;
5355  }
5356  Utilities->CallLogPop(1709);
5357 }
5358 
5359 // ---------------------------------------------------------------------------
5361 {
5362  if((TTCurrentEntryPtr == 0) || (*TTCurrentEntryPtr == ""))
5363  {
5364  return false;
5365  }
5366  TDateTime DummyTime;
5367  bool TimesPresent = false;
5368 
5369  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
5370  {
5371  for(int y = 1; y < (OneEntryTimetableMemo->Lines->Strings[x].Length() - 3); y++)
5372  {
5373  if(TrainController->CheckTimeValidity(20, OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 5), DummyTime))
5374  {
5375  TimesPresent = true;
5376  break;
5377  }
5378  }
5379  if(TimesPresent)
5380  break;
5381  }
5382  return TimesPresent;
5383 }
5384 
5385 // ---------------------------------------------------------------------------
5386 // end of Timetable editing functions
5387 // ---------------------------------------------------------------------------
5388 void __fastcall TInterface::ExitMenuItemClick(TObject *Sender)
5389 {
5390  try
5391  {
5392  TrainController->LogEvent("ExitMenuItemClick");
5393  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitMenuItemClick");
5395  {
5396  UnicodeString MessageStr =
5397  "Note that leaving the track unlinked will cause preferred directions to be lost on reloading. Prevent by linking the track then resaving. Do you still wish to exit?";
5398  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
5399  if(button == IDNO)
5400  {
5401  Utilities->CallLogPop(1711);
5402  return;
5403  }
5404  }
5405  if(FileChangedFlag)
5406  {
5407  UnicodeString MessageStr = "The railway has changed, exit without saving?";
5408  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
5409  if(button == IDNO)
5410  {
5411  Utilities->CallLogPop(1180);
5412  return;
5413  }
5414  }
5415  if((TempTTFileName != "") && FileExists(TempTTFileName))
5416  {
5417  DeleteFile(TempTTFileName);
5418  }
5419  Utilities->CallLogPop(1181);
5420  Application->Terminate();
5421  }
5422  catch(const Exception &e)
5423  {
5424  ErrorLog(140, e.Message);
5425  }
5426 }
5427 // ---------------------------------------------------------------------------
5428 
5429 void __fastcall TInterface::TrackInfoOnOffMenuItemClick(TObject *Sender)
5430 {
5431  try
5432  {
5433  TrainController->LogEvent("TrackInfoOnOffMenuItemClick");
5434  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrackInfoOnOffMenuItemClick");
5435  if(TrackInfoOnOffMenuItem->Caption == "Show")
5436  {
5437  TrackInfoOnOffMenuItem->Caption = "Hide";
5438  }
5439  else
5440  {
5441  TrackInfoOnOffMenuItem->Caption = "Show";
5442  }
5443  Utilities->CallLogPop(1183);
5444  }
5445  catch(const Exception &e)
5446  {
5447  ErrorLog(173, e.Message);
5448  }
5449 }
5450 // ---------------------------------------------------------------------------
5451 
5452 void __fastcall TInterface::TrainStatusInfoOnOffMenuItemClick(TObject *Sender)
5453 {
5454  try
5455  {
5456  TrainController->LogEvent("TrainStatusInfoOnOffMenuItemClick");
5457  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrainStatusInfoOnOffMenuItemClick");
5458  if(TrainStatusInfoOnOffMenuItem->Caption == "Show Status")
5459  {
5460  TrainStatusInfoOnOffMenuItem->Caption = "Hide Status";
5461  }
5462  else
5463  {
5464  TrainStatusInfoOnOffMenuItem->Caption = "Show Status";
5465  }
5466  Utilities->CallLogPop(1184);
5467  }
5468  catch(const Exception &e)
5469  {
5470  ErrorLog(141, e.Message);
5471  }
5472 }
5473 
5474 // ---------------------------------------------------------------------------
5475 void __fastcall TInterface::TrainTTInfoOnOffMenuItemClick(TObject *Sender)
5476 {
5477  try
5478  {
5479  TrainController->LogEvent("TrainTTInfoOnOffMenuItemClick");
5480  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrainTTInfoOnOffMenuItemClick");
5481  if(TrainTTInfoOnOffMenuItem->Caption == "Show Timetable")
5482  {
5483  TrainTTInfoOnOffMenuItem->Caption = "Hide Timetable";
5484  }
5485  else
5486  {
5487  TrainTTInfoOnOffMenuItem->Caption = "Show Timetable";
5488  }
5489  Utilities->CallLogPop(1185);
5490  }
5491  catch(const Exception &e)
5492  {
5493  ErrorLog(142, e.Message);
5494  }
5495 }
5496 
5497 // ---------------------------------------------------------------------------
5498 // Dragging Functions
5499 // ---------------------------------------------------------------------------
5500 void __fastcall TInterface::AcceptDragging(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept)
5501 {
5502 // allow in zoom out mode
5503  try
5504  {
5505 // TrainController->LogEvent("AcceptDragging"); drop this, have too many
5506  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AcceptDragging");
5507  if((Source == PerformancePanel) || (Source == PerformancePanelLabel) || (Source == PerformanceLogBox))
5508  {
5509  Accept = true;
5510  int PPLeft = PerformancePanel->Left;
5511  int PPTop = PerformancePanel->Left;
5512 
5513  PPLeft = Mouse->CursorPos.x - PerformancePanelDragStartX;
5514  PPTop = Mouse->CursorPos.y - PerformancePanelDragStartY;
5515  if((PPLeft + PerformancePanel->Width) < 32)
5516  PPLeft = 32 - PerformancePanel->Width;
5517  if(PPLeft > (MainScreen->Left + MainScreen->Width))
5518  PPLeft = MainScreen->Left + MainScreen->Width;
5519  if((PPTop + PerformancePanel->Height) < MainScreen->Top)
5520  PPTop = MainScreen->Top - PerformancePanel->Height;
5521  if(PPTop > (MainScreen->Top + MainScreen->Height - 20))
5522  PPTop = MainScreen->Top + MainScreen->Height - 20;
5523  PerformancePanel->Left = PPLeft;
5524  PerformancePanel->Top = PPTop;
5525  }
5526  else if((Source == OperatorActionPanel) || (Source == OAPanelLabel))
5527  // not the listbox because that used for selecting trains
5528  {
5529  Accept = true;
5530  int OALeft = OperatorActionPanel->Left;
5531  int OATop = OperatorActionPanel->Left;
5532 
5533  OALeft = Mouse->CursorPos.x - OperatorActionPanelDragStartX;
5534  OATop = Mouse->CursorPos.y - OperatorActionPanelDragStartY;
5535  if((OALeft + OperatorActionPanel->Width) < 32)
5536  OALeft = 32 - OperatorActionPanel->Width;
5537  if(OALeft > (MainScreen->Left + MainScreen->Width))
5538  OALeft = MainScreen->Left + MainScreen->Width;
5539  if((OATop + OperatorActionPanel->Height) < MainScreen->Top)
5540  OATop = MainScreen->Top - OperatorActionPanel->Height;
5541  if(OATop > (MainScreen->Top + MainScreen->Height - 20))
5542  OATop = MainScreen->Top + MainScreen->Height - 20;
5543  OperatorActionPanel->Left = OALeft;
5544  OperatorActionPanel->Top = OATop;
5545  }
5546  else
5547  Accept = false;
5548  Utilities->CallLogPop(1186);
5549  }
5550  catch(const Exception &e)
5551  {
5552  ErrorLog(143, e.Message);
5553  }
5554 }
5555 
5556 // ---------------------------------------------------------------------------
5557 void __fastcall TInterface::PerformancePanelStartDrag(TObject *Sender, TDragObject *&DragObject)
5558 {
5559 // allow in zoom out mode
5560  try
5561  {
5562  TrainController->LogEvent("PerformancePanelStartDrag");
5563  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PerformancePanelStartDrag");
5564  PerformancePanelDragStartX = Mouse->CursorPos.x - PerformancePanel->Left;
5565  PerformancePanelDragStartY = Mouse->CursorPos.y - PerformancePanel->Top;
5566  Utilities->CallLogPop(1187);
5567  }
5568  catch(const Exception &e)
5569  {
5570  ErrorLog(144, e.Message);
5571  }
5572 }
5573 // ---------------------------------------------------------------------------
5574 
5575 void __fastcall TInterface::OperatorActionPanelStartDrag(TObject *Sender, TDragObject *&DragObject) // new v2.2.0
5576 
5577 {
5578 // allow in zoom out mode
5579  try
5580  {
5581  TrainController->LogEvent("OperatorActionPanelStartDrag");
5582  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperatorActionPanelStartDrag");
5583  OperatorActionPanelDragStartX = Mouse->CursorPos.x - OperatorActionPanel->Left;
5584  OperatorActionPanelDragStartY = Mouse->CursorPos.y - OperatorActionPanel->Top;
5585  Utilities->CallLogPop(2091);
5586  }
5587  catch(const Exception &e)
5588  {
5589  ErrorLog(201, e.Message);
5590  }
5591 }
5592 
5593 // ---------------------------------------------------------------------------
5594 // Mouse Functions
5595 // ---------------------------------------------------------------------------
5596 void __fastcall TInterface::MainScreenMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
5597  // caller function - stops master clock
5598 {
5599 // have to allow in zoom out mode
5600  try
5601  {
5602  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MainScreenMouseDown," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
5603  bool ClockState = Utilities->Clock2Stopped;
5604  Utilities->Clock2Stopped = true;
5605 
5606  RestoreFocusPanel->Enabled = true; // these added at v2.0.0 to restore navigation keys to move screen when a panel had focus
5607  RestoreFocusPanel->Visible = true; // because then these buttons just cycled through the panel buttons. Added in place of the
5608  RestoreFocusPanel->SetFocus(); // section in ClockTimer2 where focus restored every clock cycle, because then the help screen
5609  RestoreFocusPanel->Visible = false; // was hidden. At least now help is only hidden when the screen clicked, which is normal
5610  RestoreFocusPanel->Enabled = false; // behaviour, and can tell user that can restore navigation keys just by clicking the screen
5611 
5613  {
5614  if(!Display->ZoomOutFlag)
5615  MainScreenMouseDown2(0, Button, Shift, X, Y);
5616  else
5617  MainScreenMouseDown3(0, Button, Shift, X, Y);
5618  }
5619  Utilities->Clock2Stopped = ClockState;
5620  Utilities->CallLogPop(33);
5621  }
5622  catch(const Exception &e)
5623  {
5624  ErrorLog(19, e.Message);
5625  }
5626 }
5627 
5628 // ---------------------------------------------------------------------------
5629 void TInterface::MainScreenMouseDown2(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
5630 {
5631  try
5632  {
5633  TrainController->LogEvent("MainScreenMouseDown2," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
5634  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",MainScreenMouseDown2," + AnsiString(Button) + "," + AnsiString(X) +
5635  "," + AnsiString(Y));
5636  // unplot GapFlash graphics if plotted & cancel gap flashing (either key down)
5637  // but not in ZoomOut mode - so can switch between modes & keep gaps flashing
5639  {
5642  Track->GapFlashFlag = false;
5643  }
5644  int HLoc, VLoc;
5645  Track->GetTrackLocsFromScreenPos(1, HLoc, VLoc, X, Y);
5646  int NoOffsetX, NoOffsetY;
5647  Track->GetTruePositionsFromScreenPos(0, NoOffsetX, NoOffsetY, X, Y);
5648  if(Button == mbRight) // track, PrefDir or text erase, PrefDir/route truncate, or take signaller control of train
5649  {
5650  // this routine new at v2.1.0. Allows railway moving for zoom-in mode when no element at HLoc & VLoc
5651  int Dummy; // unused in next function
5652  AnsiString Text = ""; //needed for TextFound but not used
5653  if(!Track->TrackElementPresentAtHV(0, HLoc, VLoc) && !Track->InactiveTrackElementPresentAtHV(0, HLoc, VLoc) && !Track->UserGraphicPresentAtHV(0, X, Y, Dummy) &&
5654  !TextHandler->TextFound(0, X + (Display->DisplayOffsetH * 16), Y + (Display->DisplayOffsetV * 16), Text))
5655  {
5658  WholeRailwayMoving = true;
5659  Screen->Cursor = TCursor(-22); // Four arrows;
5660  }
5661 
5662  else if(Level2TrackMode == AddText)
5663  {
5664  TrainController->LogEvent("mbRight + AddText");
5666  if(TextHandler->TextFound(1, NoOffsetX, NoOffsetY, Text))
5667  {
5668  if(TextHandler->TextErase(0, NoOffsetX, NoOffsetY, Text)) // erase text in vector
5669  {
5671  if(NoRailway())
5672  {
5673  EditMenu->Enabled = false;
5674  }
5675  else
5676  EditMenu->Enabled = true;
5677  }
5678  }
5679  SetLevel2TrackMode(57); // to remove 'move text' if last text item removed
5680  Utilities->CallLogPop(34);
5681  return;
5682  }
5683  else if(Level2TrackMode == AddGraphic)
5684  {
5685  TrainController->LogEvent("mbRight + AddGraphic");
5686  if(Track->UserGraphicVector.empty()) // no user graphics
5687  {
5688  Utilities->CallLogPop(2180);
5689  return;
5690  }
5691  int UGIVecPos;
5692  if(Track->UserGraphicPresentAtHV(1, X, Y, UGIVecPos))
5693  {
5694  Track->UserGraphicVector.erase(Track->UserGraphicVector.begin() + UGIVecPos);
5696  if(NoRailway())
5697  {
5698  EditMenu->Enabled = false;
5699  }
5700  else
5701  EditMenu->Enabled = true;
5702  }
5703  Utilities->CallLogPop(2181);
5704  return;
5705  }
5706 
5707  else if(Level2TrackMode == AddTrack)
5708  {
5709  TrainController->LogEvent("mbRight + AddTrack");
5710  bool TrackEraseSuccessfulFlag;
5711  int ErasedTrackVectorPosition;
5712  Screen->Cursor = TCursor(-11); // Hourglass;
5713  Track->EraseTrackElement(1, HLoc, VLoc, ErasedTrackVectorPosition, TrackEraseSuccessfulFlag, true);
5714  if(TrackEraseSuccessfulFlag)
5715  {
5716  if(ErasedTrackVectorPosition > -1)
5717  EveryPrefDir->RealignAfterTrackErase(0, ErasedTrackVectorPosition);
5720  ClearandRebuildRailway(5); // to ensure location named elements plotted correctly & replot the grid if required
5721  SetGapsButton->Enabled = false; // if conditions have changed need to reset buttons, best not calling SetLevel2TrackMode as that
5722  TrackOKButton->Enabled = false; // calls Clearand.. if gridflag set & takes a long time
5723  if(Track->GapsUnset(1))
5724  {
5725  SetGapsButton->Enabled = true;
5726  }
5727  // only enable if there are gaps still to be set (returns false for no track)
5728  else
5729  {
5730  if(!(Track->NoActiveTrack(0)) && !(Track->IsTrackFinished()))
5731  {
5732  TrackOKButton->Enabled = true;
5733  }
5734  // TrackOK only enabled if track exists, there are no unset gaps, and track not finished
5735  }
5736  if(!(Track->IsTrackFinished())) // can only set lengths for several elements together if TrackFinished
5737  {
5738  SetLengthsButton->Enabled = false;
5739  }
5740 // if(NoRailway()) dropped at v2.6.0 to allow edits during AddTrack
5741 // {
5742 // EditMenu->Enabled = false;
5743 // }
5744 // else
5745  EditMenu->Enabled = true;
5746  }
5747  Screen->Cursor = TCursor(-2); // Arrow
5748  Utilities->CallLogPop(35);
5749  return;
5750  }
5751  else if(Level2TrackMode == DistanceContinuing) // new for extended distances (similar to PrefDirContinuing)
5752  {
5753  TrainController->LogEvent("mbRight + DistanceContinuing");
5755  bool LeadingPointsAtLastElement = false;
5756  if(ConstructPrefDir->GetPrefDirTruncateElement(0, HLoc, VLoc))
5757  {
5758  if(ConstructPrefDir->PrefDirSize() == 0)
5759  {
5761  SetLevel1Mode(64);
5763  SetLevel2TrackMode(51); // calls ClearandRebuildRailway to show length erased & sets back to start
5764  Utilities->CallLogPop(1526);
5765  return;
5766  }
5769  ConstructPrefDir->CalcDistanceAndSpeed(0, OverallDistance, OverallSpeedLimit, LeadingPointsAtLastElement);
5770  if(!LeadingPointsAtLastElement)
5771  {
5772  TrackLengthPanel->Visible = true;
5773  TrackLengthPanel->SetFocus();
5774  InfoPanel->Visible = true;
5775  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
5776  RestoreAllDefaultLengthsButton->Enabled = true;
5777  ResetDefaultLengthButton->Enabled = true;
5778  LengthOKButton->Enabled = true;
5779  DistanceBox->Text = AnsiString(OverallDistance);
5780  if(OverallSpeedLimit > -1)
5781  SpeedLimitBox->Text = AnsiString(OverallSpeedLimit);
5782  else
5783  SpeedLimitBox->Text = "Mixed";
5784  }
5785  else
5786  {
5787  TrackLengthPanel->Visible = true;
5788  TrackLengthPanel->SetFocus();
5789  InfoPanel->Visible = true;
5790  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Can't end on leading points, continue or truncate";
5791  RestoreAllDefaultLengthsButton->Enabled = false;
5792  ResetDefaultLengthButton->Enabled = false;
5793  LengthOKButton->Enabled = false;
5794  }
5796  }
5797  Utilities->CallLogPop(36);
5798  return;
5799  }
5800 
5801  else if(Level2PrefDirMode == PrefDirContinuing) // truncate
5802  {
5803  TrainController->LogEvent("mbRight + PrefDirContinuing");
5805 // RlyFile = false; - don't alter this just for PrefDir changes
5806  if(ConstructPrefDir->GetPrefDirTruncateElement(1, HLoc, VLoc))
5807  {
5808  if(ConstructPrefDir->PrefDirSize() == 0)
5809  {
5811  SetLevel1Mode(14); // all PrefDir truncated
5812  Utilities->CallLogPop(37);
5813  return;
5814  }
5816  }
5818  SetLevel2PrefDirMode(0); // calls ClearandRebuildRailway to show length erased & sets back to start
5819  Utilities->CallLogPop(38);
5820  return;
5821  }
5822 
5823  else if((Level1Mode == PrefDirMode) && (Level2PrefDirMode != PrefDirContinuing) && (Level2PrefDirMode != PrefDirSelecting)) // delete element
5824  {
5825  TrainController->LogEvent("mbRight + != PrefDirContinuing");
5827 // RlyFile = false; - don't alter this just for PrefDir changes
5830  SetLevel1Mode(15); // calls ClearandRebuildRailway to show length erased & sets back to start
5831  Utilities->CallLogPop(39);
5832  return;
5833  }
5834 
5835  else if((Level2OperMode == Operating) || (Level2OperMode == PreStart)) // disallow when paused, but allow some parts in prestart
5836  {
5837  TrainController->LogEvent("mbRight + OperMode");
5838  bool FoundFlag;
5839  int VecPos = Track->GetVectorPositionFromTrackMap(1, HLoc, VLoc, FoundFlag);
5840  if(FoundFlag && (Level2OperMode != PreStart)) // disallow signaller control in PreStart
5841  {
5843  // signaller control of train
5844  if(SelectedTrainID > -1)
5845  {
5848  if((Train.LeadElement == -1) || (Track->TrackElementAt(788, Train.LeadElement).Conn[Train.LeadExitPos] == -1))
5849  {
5850  if(Train.TrainMode == Signaller)
5851  {
5853  }
5854  }
5855  if((Train.Stopped()) || (Train.TrainFailed && !(Train.TrainMode == Signaller)) ||
5857  !Train.StepForwardFlag))
5858  // don't allow signaller popup menu in timetable mode unless stopped,
5859  // or when coming to a stop or leaving at a continuation when under signaller control
5860  // or when failed
5861  {
5862  // don't allow selection if another stopped train at a bridge position
5863  if(Track->TrackElementAt(630, VecPos).TrackType == Bridge)
5864  {
5865  int TrainID01 = Track->TrackElementAt(631, VecPos).TrainIDOnBridgeTrackPos01;
5866  int TrainID23 = Track->TrackElementAt(632, VecPos).TrainIDOnBridgeTrackPos23;
5867  if((TrainID01 > -1) && (TrainID23 > -1))
5868  {
5869  TrainController->StopTTClockMessage(0, "Can't select a train at a bridge when another train is at the same bridge");
5870  Utilities->CallLogPop(1103);
5871  return;
5872  }
5873  }
5874  if(Train.TrainMode == Timetable)
5875  {
5876  TakeSignallerControlMenuItem->Enabled = true;
5877  TimetableControlMenuItem->Enabled = false;
5878  ChangeDirectionMenuItem->Enabled = false;
5879  MoveForwardsMenuItem->Enabled = false;
5880  SignallerJoinedByMenuItem->Enabled = false;
5881  RepairFailedTrainMenuItem->Enabled = false;
5882  StepForwardMenuItem->Enabled = false;
5883  RemoveTrainMenuItem->Enabled = false;
5884  PassRedSignalMenuItem->Enabled = false;
5885  SignallerControlStopMenuItem->Enabled = false;
5886  }
5887  else // signaller mode
5888  {
5889  TakeSignallerControlMenuItem->Enabled = false;
5890  if((Train.Crashed) || (Train.Derailed))
5891  {
5892  TimetableControlMenuItem->Enabled = false;
5893  ChangeDirectionMenuItem->Enabled = false;
5894  MoveForwardsMenuItem->Enabled = false;
5895  SignallerJoinedByMenuItem->Enabled = false;
5896  RepairFailedTrainMenuItem->Enabled = false;
5897  StepForwardMenuItem->Enabled = false;
5898  PassRedSignalMenuItem->Enabled = false;
5899  SignallerControlStopMenuItem->Enabled = false;
5900  RemoveTrainMenuItem->Enabled = true;
5901  }
5902  else if(Train.Stopped())
5903  {
5904  if(Train.TimetableFinished)
5905  {
5906  TimetableControlMenuItem->Enabled = false;
5907  }
5908  else
5909  {
5910  if(Train.RestoreTimetableLocation == "") // en route
5911  {
5912  TimetableControlMenuItem->Enabled = true;
5913  }
5914  else
5915  {
5916  // obtain train location & check if OK for restoration of tt control
5917  AnsiString LocName = "";
5918  if(Train.LeadElement > -1)
5919  {
5920  LocName = Track->TrackElementAt(802, Train.LeadElement).ActiveTrackElementName;
5921  }
5922  if((LocName == "") && (Train.MidElement > -1))
5923  {
5924  LocName = Track->TrackElementAt(803, Train.MidElement).ActiveTrackElementName;
5925  }
5926  if(Train.RestoreTimetableLocation == LocName)
5927  {
5928  TimetableControlMenuItem->Enabled = true;
5929  }
5930  else
5931  {
5932  TimetableControlMenuItem->Enabled = false;
5933  }
5934  }
5935  }
5936 // don't allow ChangeDirection if lead or mid elements (but not lag or next) -1, or lead, mid, lag or next elements continuations
5937  ChangeDirectionMenuItem->Enabled = true;
5938  if(Train.LeadElement > -1)
5939  {
5941  {
5942  ChangeDirectionMenuItem->Enabled = false;
5943  }
5944  if(Track->TrackElementAt(791, Train.LeadElement).Conn[Train.LeadExitPos] > -1)
5945  {
5946  if(Track->TrackElementAt(792, (Track->TrackElementAt(793, Train.LeadElement).Conn[Train.LeadExitPos]))
5947  .TrackType == Continuation)
5948  {
5949  ChangeDirectionMenuItem->Enabled = false;
5950  }
5951  }
5952  }
5953  else
5954  ChangeDirectionMenuItem->Enabled = false;
5955  if(Train.MidElement > -1)
5956  {
5958  {
5959  ChangeDirectionMenuItem->Enabled = false;
5960  }
5961  }
5962  else
5963  ChangeDirectionMenuItem->Enabled = false;
5964  if(Train.LagElement > -1)
5965  {
5967  {
5968  ChangeDirectionMenuItem->Enabled = false;
5969  }
5970  }
5971  RemoveTrainMenuItem->Enabled = true;
5972  SignallerControlStopMenuItem->Enabled = false;
5973  SignallerJoinedByMenuItem->Enabled = false;
5974  RepairFailedTrainMenuItem->Enabled = false;
5975  StepForwardMenuItem->Enabled = false;
5976  MoveForwardsMenuItem->Enabled = false;
5977  PassRedSignalMenuItem->Enabled = false;
5978  if(Train.AbleToMove(0))
5979  {
5980  MoveForwardsMenuItem->Enabled = true;
5982  StepForwardMenuItem->Enabled = true; // added 'if' condition for v1.3.2 due to Carwyn Thomas error,
5983  } // fails on trying to calc AutoSig time delay for resetting signals
5984  if(Train.AbleToMoveButForSignal(0)) // may not be in AutoSigs route but disallow anyway as not needed at continuation
5985  {
5986  PassRedSignalMenuItem->Enabled = true;
5987  StepForwardMenuItem->Enabled = true;
5988  }
5989  TTrain *AdjacentTrain;
5990  if(Train.IsThereAnAdjacentTrain(0, AdjacentTrain))
5991  {
5992  SignallerJoinedByMenuItem->Enabled = true;
5993  }
5994  if(Train.TrainFailed)
5995  {
5996  RepairFailedTrainMenuItem->Enabled = true;
5997  }
5998  }
5999  else // train moving under signaller control - only permit restoration of TT control when stopped as could be in
6000  // mid move, & SetTrainMovementValues only intended to be called when stopped
6001  {
6002  TimetableControlMenuItem->Enabled = false;
6003  ChangeDirectionMenuItem->Enabled = false;
6004  RemoveTrainMenuItem->Enabled = false;
6005  MoveForwardsMenuItem->Enabled = false;
6006  SignallerJoinedByMenuItem->Enabled = false;
6007  RepairFailedTrainMenuItem->Enabled = false;
6008  PassRedSignalMenuItem->Enabled = false;
6009  StepForwardMenuItem->Enabled = false;
6010  SignallerControlStopMenuItem->Enabled = true;
6011  }
6012  }
6013  TrainHeadCodeMenuItem->Caption = Train.HeadCode + ":";
6014  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
6016  PopupMenu->Popup(X, Y); // menu stops everything so reset timetable time when restarts
6017  TrainController->BaseTime = TDateTime::CurrentDateTime();
6019  Utilities->CallLogPop(40);
6020  return;
6021  }
6022  }
6023  }
6024 
6025  if(RouteMode == RouteContinuing) // clear a single element (clears whether use left or right mouse button) +allow in PreStart
6026  {
6027  TrainController->LogEvent("mbRight + RouteContinuing");
6029  Utilities->CallLogPop(41);
6030  return;
6031  }
6032 
6033  else if(RouteCancelFlag) // allow in PreStart
6034  {
6035  TrainController->LogEvent("mbRight + RouteCancelFlag");
6036  Screen->Cursor = TCursor(-11); // Hourglass;
6037  // stop clock as sometimes takes several seconds
6038  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
6040  if(AllRoutes->GetAllRoutesTruncateElement(0, HLoc, VLoc, ConsecSignalsRoute)) // updates LockedRouteClass
6041  {
6042  ClearandRebuildRailway(6); // to replot new shorter route
6043  }
6045  TrainController->BaseTime = TDateTime::CurrentDateTime();
6047  Screen->Cursor = TCursor(-2); // Arrow
6048  }
6049 
6050  else // gap flashing, don't allow to interfere with RouteCancelFlag
6051  {
6052  TrainController->LogEvent("mbRight, GapFlashingInOperOrPreStartMode");
6053  int Position;
6054  TTrackElement TrackElement;
6055  if(Track->FindNonPlatformMatch(4, HLoc, VLoc, Position, TrackElement));
6056  {
6057  if((TrackElement.TrackType == GapJump) && (TrackElement.Conn[0] > -1))
6058  {
6059  if((TrackElement.TrainIDOnElement == -1) && (Track->TrackElementAt(818, TrackElement.Conn[0]).TrainIDOnElement == -1))
6060  { // don't flash if train on either gap element
6061  Track->GapFlashGreenPosition = TrackElement.Conn[0];
6066  Track->GapFlashRedPosition = Position;
6071  Track->GapFlashFlag = true;
6072  }
6073  }
6074  }
6075  Utilities->CallLogPop(42);
6076  return; // covers above else & included here in case any more usermodes added later
6077  }
6078  }
6079 
6080  // deal with gap selection - if no other right button selection - apply for any mode (also included in OperMode above)
6081  TrainController->LogEvent("mbRight, GapFlashingNotOperOrPreStartMode");
6082  int Position;
6083  TTrackElement TrackElement;
6084  if(Track->FindNonPlatformMatch(18, HLoc, VLoc, Position, TrackElement));
6085  {
6086  if((TrackElement.TrackType == GapJump) && (TrackElement.Conn[0] > -1))
6087  {
6088  if((TrackElement.TrainIDOnElement == -1) && (Track->TrackElementAt(819, TrackElement.Conn[0]).TrainIDOnElement == -1))
6089  { // don't flash if train on either gap element
6090  Track->GapFlashGreenPosition = TrackElement.Conn[0];
6094  Track->GapFlashRedPosition = Position;
6098  Track->GapFlashFlag = true;
6099  }
6100  }
6101  }
6102  Utilities->CallLogPop(67);
6103  return; // covers above else & included here in case any more usermodes added later
6104  }
6105 
6106 // Left Mouse Button Functions
6107  if(RouteCancelFlag)
6109  mbLeftDown = true;
6110 
6111  if(Level2TrackMode == AddTrack)
6112  {
6113  TrainController->LogEvent("mbLeft + AddTrack");
6114  Screen->Cursor = TCursor(-11); // Hourglass;
6116  bool TrackLinkingRequiredFlag;
6117  int CurrentTag;
6118  TSpeedButton *TempSpeedButton = 0;
6119  if(CurrentSpeedButton)
6120  {
6121  CurrentTag = CurrentSpeedButton->Tag;
6122  TempSpeedButton = CurrentSpeedButton;
6123  }
6124  else
6125  CurrentTag = 0;
6126  bool InternalChecks = true;
6127  Track->PlotAndAddTrackElement(1, CurrentTag, 0, HLoc, VLoc, TrackLinkingRequiredFlag, InternalChecks);
6128  // above now has extra zero 'Aspect' parameter at v2.2.0 so can distinguish between adding track and pasting
6129  EditMenu->Enabled = true;
6130  if(Track->NamedLocationElementAt(1, HLoc, VLoc))
6131  ClearandRebuildRailway(7); // so named location graphics plotted correctly
6132  if(TrackLinkingRequiredFlag)
6133  {
6134  Track->SetTrackFinished(false);
6135  }
6136  SetTrackBuildImages(10);
6137  SetGapsButton->Enabled = false; // if conditions have changed need to reset buttons, best not calling SetLevel2TrackMode as that
6138  TrackOKButton->Enabled = false; // calls Clearand.. if gridflag set & takes a long time
6139  if(Track->GapsUnset(2))
6140  {
6141  SetGapsButton->Enabled = true;
6142  }
6143  // only enable if there are gaps still to be set (returns false for no track)
6144  else
6145  {
6146  if(!(Track->NoActiveTrack(1)) && !(Track->IsTrackFinished()))
6147  {
6148  TrackOKButton->Enabled = true;
6149  }
6150  // TrackOK only enabled if track exists, there are no unset gaps, and track not finished
6151  }
6152  if(!(Track->IsTrackFinished())) // can only set lengths for several elements together if TrackFinished
6153  {
6154  SetLengthsButton->Enabled = false;
6155  }
6156  if(TempSpeedButton) // restore button if was pressed
6157  {
6158  CurrentSpeedButton = TempSpeedButton;
6159  CurrentSpeedButton->Down = true;
6160  }
6161  Screen->Cursor = TCursor(-2); // Arrow
6162  Utilities->CallLogPop(44);
6163  return;
6164  }
6165 
6166  else if(Level2TrackMode == AddGraphic)
6167  {
6168  TrainController->LogEvent("mbLeft + AddGraphic");
6169  ResetChangedFileDataAndCaption(24, false);
6170  TUserGraphicItem NewGI;
6171  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.find(SelectedGraphicFileName);
6172  if(UGMIt != Track->UserGraphicMap.end()) // if it is the end then nothing was found
6173  {
6174  NewGI.UserGraphic = UGMIt->second;
6175  NewGI.Width = UGMIt->second->Width;
6176  NewGI.Height = UGMIt->second->Height;
6178  NewGI.HPos = X + (Display->DisplayOffsetH * 16);
6179  NewGI.VPos = Y + (Display->DisplayOffsetV * 16);
6180  Track->UserGraphicVector.push_back(NewGI);
6181  Display->PlotAndAddUserGraphic(1, NewGI);
6182  }
6183  else
6184  {
6185  ShowMessage("Unable to find graphic file " + SelectedGraphicFileName + ". Check it still exists.");
6186  Utilities->CallLogPop(2195);
6187  return;
6188  }
6189  MoveTextOrGraphicButton->Enabled = true;
6190  EditMenu->Enabled = true;
6191  Utilities->CallLogPop(2182);
6192  return;
6193  }
6194 
6195  else if(Level2TrackMode == AddLocationName)
6196  {
6197  TrainController->LogEvent("mbLeft + AddLocationName");
6199  bool FoundFlag;
6200  TTrackElement TrackElement;
6201  AnsiString NameString;
6202  TTrack::TIMPair InactivePair = Track->GetVectorPositionsFromInactiveTrackMap(1, HLoc, VLoc, FoundFlag);
6203  if(!FoundFlag)
6204  {
6205  Utilities->CallLogPop(45);
6206  return; // inactive element not found (has to be a platform or named non-station location, can't select any other element)
6207  }
6208  TTrackElement& InactiveTrackElement1 = Track->InactiveTrackElementAt(28, InactivePair.first);
6209  TTrackElement& InactiveTrackElement2 = Track->InactiveTrackElementAt(29, InactivePair.second); // may be same element if only 1
6210  TTrackElement& ValidElement = InactiveTrackElement1;
6211  unsigned int ValidPosition;
6212  if((InactiveTrackElement1.TrackType != Platform) && (InactiveTrackElement2.TrackType != Platform) &&
6213  (InactiveTrackElement1.TrackType != NamedNonStationLocation) && (InactiveTrackElement2.TrackType != NamedNonStationLocation) &&
6214  (InactiveTrackElement1.TrackType != Concourse) && (InactiveTrackElement2.TrackType != Concourse))
6215  {
6216  Utilities->CallLogPop(46);
6217  return; // element not valid
6218  }
6219  if((InactiveTrackElement1.TrackType == Platform) || (InactiveTrackElement1.TrackType == NamedNonStationLocation) ||
6220  (InactiveTrackElement1.TrackType == Concourse))
6221  {
6222  ValidElement = InactiveTrackElement1;
6223  ValidPosition = InactivePair.first;
6224  }
6225  else if((InactiveTrackElement2.TrackType == Platform) || (InactiveTrackElement2.TrackType == NamedNonStationLocation) ||
6226  (InactiveTrackElement2.TrackType == Concourse))
6227  {
6228  ValidElement = InactiveTrackElement2;
6229  ValidPosition = InactivePair.second;
6230  }
6231  // now have required element as ValidElement & position in InactiveTrackvector as ValidPosition
6232 
6233  // put a square box round element to show selection
6234  Display->Rectangle(0, HLoc * 16, VLoc * 16, clB0G0R5, 0, 2);
6235  LocationNameTextBox->Visible = true;
6236  LocationNameTextBox->SetFocus();
6237  NameString = Track->GetLocationName(ValidPosition);
6238  LocationNameTextBox->Text = NameString;
6239  InfoPanel->Visible = true;
6240  InfoPanel->Caption = "NAMING LOCATIONS: Enter name, 'Carriage Return' to accept, 'Escape' to quit";
6241 
6242  Track->LNPendingList.clear();
6243  Track->LNPendingList.insert(Track->LNPendingList.end(), ValidPosition);
6244  Level2TrackMode = NoTrackMode; // if leave as AddLocationName can select other squares before enter name
6245  Utilities->CallLogPop(47);
6246  return;
6247  }
6248 
6249  else if(Level2TrackMode == DistanceStart) // new for extended distances - similar to !PrefDirContinuing
6250  // prior to selecting start element
6251  {
6252  TrainController->LogEvent("mbLeft + DistanceStart");
6254  if(ConstructPrefDir->GetPrefDirStartElement(0, HLoc, VLoc))
6255  {
6258  SetLevel1Mode(65);
6260  SetLevel2TrackMode(30);
6261  }
6262  Utilities->CallLogPop(48);
6263  return;
6264  }
6265 
6266  else if(Level2TrackMode == DistanceContinuing) // new for extended distances - similar to PrefDirContinuing
6267  // prior to selecting finish element
6268  {
6269  TrainController->LogEvent("mbLeft + DistanceContinuing");
6271  bool FinishElement = false, LeadingPointsAtLastElement = false;
6272  Screen->Cursor = TCursor(-11); // Hourglass;
6273  if((ConstructPrefDir->PrefDirSize() != 1) || (ConstructPrefDir->GetFixedPrefDirElementAt(181, 0).HLoc != HLoc) ||
6274  (ConstructPrefDir->GetFixedPrefDirElementAt(182, 0).VLoc != VLoc))
6275  { // not same as start element
6276  if(ConstructPrefDir->GetNextPrefDirElement(0, HLoc, VLoc, FinishElement))
6277  {
6280  ConstructPrefDir->CalcDistanceAndSpeed(1, OverallDistance, OverallSpeedLimit, LeadingPointsAtLastElement);
6281  if(FinishElement)
6282  {
6283  TrackLengthPanel->Visible = true;
6284  TrackLengthPanel->SetFocus();
6285  InfoPanel->Visible = true;
6286  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Set values (overall length), or right click to cancel/truncate";
6287  RestoreAllDefaultLengthsButton->Enabled = true;
6288  ResetDefaultLengthButton->Enabled = true;
6289  LengthOKButton->Enabled = true;
6290  DistanceBox->Text = AnsiString(OverallDistance);
6291  if(OverallSpeedLimit > -1)
6292  SpeedLimitBox->Text = AnsiString(OverallSpeedLimit);
6293  else
6294  SpeedLimitBox->Text = "Mixed";
6296  Screen->Cursor = TCursor(-2); // Arrow
6297  Utilities->CallLogPop(1527);
6298  return;
6299  }
6300  else
6301  {
6302  if(!LeadingPointsAtLastElement)
6303  {
6304  TrackLengthPanel->Visible = true;
6305  TrackLengthPanel->SetFocus();
6306  InfoPanel->Visible = true;
6307  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
6308  RestoreAllDefaultLengthsButton->Enabled = true;
6309  ResetDefaultLengthButton->Enabled = true;
6310  LengthOKButton->Enabled = true;
6311  DistanceBox->Text = AnsiString(OverallDistance);
6312  if(OverallSpeedLimit > -1)
6313  SpeedLimitBox->Text = AnsiString(OverallSpeedLimit);
6314  else
6315  SpeedLimitBox->Text = "Mixed";
6316  // Level2TrackMode = DistanceContinuing;
6317  // SetLevel2TrackMode();
6318  }
6319  else
6320  {
6321  TrackLengthPanel->Visible = true;
6322  TrackLengthPanel->SetFocus();
6323  InfoPanel->Visible = true;
6324  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Can't end on leading points, need to continue or truncate";
6325  RestoreAllDefaultLengthsButton->Enabled = false;
6326  ResetDefaultLengthButton->Enabled = false;
6327  LengthOKButton->Enabled = false;
6328  // Level2TrackMode = DistanceContinuing;
6329  // SetLevel2TrackMode();
6330  }
6331  }
6332  }
6333  }
6334  else // same as start element
6335  {
6338  SetLevel2TrackMode(54);
6339  Screen->Cursor = TCursor(-2); // Arrow
6340  Utilities->CallLogPop(1713);
6341  return;
6342  }
6344  Screen->Cursor = TCursor(-2); // Arrow
6345  Utilities->CallLogPop(1490);
6346  return;
6347  }
6348 
6349  else if(Level2TrackMode == GapSetting)
6350  {
6351  TrainController->LogEvent("mbLeft + GapSetting");
6353  // HighLightOneGap already called once from SetLevel2TrackMode so have all gap element values set
6354  // & it is highlighted
6355  if(!(Track->FindSetAndDisplayMatchingGap(1, HLoc, VLoc)))
6356  {
6357  Utilities->CallLogPop(50);
6358  return; // true if finds one
6359  }
6360  InfoPanel->Visible = true;
6361  InfoPanel->Caption = "CONNECTING GAPS: Connecting element selected";
6362  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
6363  Delay(0, 500); // 500 msec delay before next selection requested
6364 
6365  // ClearandRebuildRailway(8);//get rid of gap selections
6366  // need to call this later when new gap displayed, else old gap remains
6367 
6368  // now back to highlighting next gap
6369  // bool LocError = false;
6370  if(!(HighLightOneGap(1, HLoc, VLoc)))
6371  {
6372  // all gaps set
6373  ShowMessage("All gaps set");
6374  if(Level2TrackMode == AddTrack)
6375  {
6377  SetLevel1Mode(66);
6378  SetLevel2TrackMode(31);
6379  }
6380  else
6381  {
6383  SetLevel1Mode(37);
6384  }
6385  ClearandRebuildRailway(9); // get rid of last gap ellipse
6386  Utilities->CallLogPop(51);
6387  return;
6388  }
6389  // here if one gap highlighted so return to user to allow corresponding gap to be selected
6390  // by another call to MainScreenMouseDown
6391  }
6392 
6393  else if(Level2TrackMode == AddText)
6394  {
6395  TrainController->LogEvent("mbLeft + AddText");
6397  // X & Y are relative to Display output, but TextBox is placed relative to Form
6398  // if mouse position on first character of an existing piece of text reload it into the editor
6399 
6400  bool TextFoundFlag = false;
6401  int TrueX = 0, TrueY = 0;
6402  AnsiString ExistingText = "";
6404  TFont *ExistingTextFont = new TFont;
6405  int ExistingTextHPos = 0, ExistingTextVPos = 0;
6406  Track->GetTruePositionsFromScreenPos(1, TrueX, TrueY, X, Y);
6407  if(!TextHandler->TextVector.empty())
6408  {
6409  for(TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin(); TextPtr--)
6410  {
6411  if((TrueX >= TextPtr->HPos) && (TrueX < (TextPtr->HPos + abs(TextPtr->Font->Height))) && (TrueY >= TextPtr->VPos) && (TrueY <
6412  (TextPtr->VPos + abs(TextPtr->Font->Height))))
6413  {
6414  ExistingText = TextPtr->TextString;
6415  ExistingTextFont->Assign(TextPtr->Font);
6416  ExistingTextHPos = TextPtr->HPos;
6417  ExistingTextVPos = TextPtr->VPos;
6418  TextFoundFlag = true;
6419  TextHandler->TextErase(9, TrueX, TrueY, ExistingText);
6420  break;
6421  } // if ....
6422  } // for TextPtr...
6423  } // if !TextVector...
6424 
6425  if(TextFoundFlag)
6426  {
6427  TextBox->Left = ExistingTextHPos + Display->Left() - (Display->DisplayOffsetH * 16) - 3;
6428  TextBox->Top = ExistingTextVPos + Display->Top() - (Display->DisplayOffsetV * 16) - 3;
6429  TextBox->Font->Assign(ExistingTextFont);
6430  Display->SetFont(ExistingTextFont);
6431  Text_X = ExistingTextHPos;
6432  Text_Y = ExistingTextVPos;
6433  }
6434  else
6435  {
6436  TextBox->Left = (TextOrUserGraphicGridVal * div((Display->Left() + X), TextOrUserGraphicGridVal).quot) - 3;
6437  TextBox->Top = (TextOrUserGraphicGridVal * div((Display->Top() + Y), TextOrUserGraphicGridVal).quot) - 3;
6438  TextBox->Font->Assign(Display->GetFont());
6439  Text_X = TextOrUserGraphicGridVal * div(NoOffsetX, TextOrUserGraphicGridVal).quot;
6440  Text_Y = TextOrUserGraphicGridVal * div(NoOffsetY, TextOrUserGraphicGridVal).quot;
6441  }
6442  TextBox->Visible = true;
6443  TextBox->SetFocus();
6444  if(TextFoundFlag)
6445  TextBox->Text = ExistingText;
6446  else
6447  TextBox->Text = "New Text: CR=end, ESC=quit";
6448  TextBox->Width = (abs(TextBox->Font->Height) * TextBox->Text.Length() * 0.7);
6449  TextBox->SelectAll();
6450  delete ExistingTextFont;
6451  ClearandRebuildRailway(29); // to remove old text if replaced
6453  Utilities->CallLogPop(1775);
6454  return; // If text input go no further
6455  }
6456 
6458  {
6459  TrainController->LogEvent("mbLeft + MoveTextOrGraphic");
6461  // int HPosInput;// = X + (Display->DisplayOffsetH * 16);
6462  // int VPosInput;// = Y + (Display->DisplayOffsetV * 16);
6463  // Track->GetTruePositionsFromScreenPos(HPosInput, VPosInput, X, Y);
6464  // StartX = X + (Display->DisplayOffsetH * 16);
6465  // StartY = Y + (Display->DisplayOffsetV * 16);
6468  if(!TextFoundFlag) // give precedence to text
6469  {
6471  }
6472  Utilities->CallLogPop(53);
6473  return; // if text move selected don't permit anything else
6474  }
6475 
6476  else if(Level2TrackMode == TrackSelecting)
6477 /* When 'select' chosen from the Edit menu (only available in 'AddTrack') conditions are set ready to enclose a rectangular screen area
6478  using MouseMove. When MouseDown occurs the starting point is marked (wrt whole railway, not just the screen) and stored in
6479  SelectStartPair. If the mouse button is released and a new start position selected then the earlier one is discarded. Providing the
6480  button is held down subsequent actions occur during MouseMove (to display the changing rectangle) and MouseUp to define the final
6481  selected rectangle.
6482 */
6483  {
6484  TrainController->LogEvent("mbLeft + TrackSelecting");
6485  ClearandRebuildRailway(10); // to get rid of earlier rectangles
6486  SelectStartPair.first = HLoc;
6487  SelectStartPair.second = VLoc;
6488  }
6489 
6490  else if((Level2TrackMode == CopyMoving) || (Level2TrackMode == CutMoving))
6491 /* The same actions apply on MouseDown whether Copy or Cut selected from the menu. First the horizontal and vertical mouse position is
6492  checked and unless it lies within the selected rectangle and not within 4 pixels of an edge the pickup fails and the function returns.
6493  Otherwise flag SelectPickedUp is set to true (to allow it to move during MouseMove and remain in place at MouseUp) and the mouse position
6494  is saved in SelectBitmapMouseLocX & Y for use later in MouseMove & MouseUp.
6495 */
6496  {
6497  TrainController->LogEvent("mbLeft + CopyMoving or CutMoving");
6499  if((X < ((SelectBitmapHLoc - Display->DisplayOffsetH) * 16) + 4) ||
6500  (X > ((SelectBitmapHLoc + (SelectBitmap->Width / 16) - Display->DisplayOffsetH) * 16) - 4))
6501  {
6502  SelectPickedUp = false;
6503  Utilities->CallLogPop(54);
6504  return; // within 4 pixels of outside of horizontal area (4 pixels are so can't push selection off edge of screen)
6505  }
6506  if((Y < ((SelectBitmapVLoc - Display->DisplayOffsetV) * 16) + 4) ||
6507  (Y > ((SelectBitmapVLoc + (SelectBitmap->Height / 16) - Display->DisplayOffsetV) * 16) - 4))
6508  {
6509  SelectPickedUp = false;
6510  Utilities->CallLogPop(55);
6511  return; // within 4 pixels of outside of vertical area (4 pixels are so can't push selection off edge of screen)
6512  }
6513  else
6514  {
6515  SelectPickedUp = true;
6516  }
6519  }
6520 
6522  {
6523  TrainController->LogEvent("mbLeft + != PrefDirContinuing");
6524  ResetChangedFileDataAndCaption(15, false);
6525 // RlyFile = false; - don't alter this just for PrefDir changes
6526  if(ConstructPrefDir->GetPrefDirStartElement(1, HLoc, VLoc))
6527  {
6531  }
6532  Utilities->CallLogPop(56);
6533  return;
6534  }
6535 
6537  {
6538  TrainController->LogEvent("mbLeft + PrefDirContinuing");
6539  ResetChangedFileDataAndCaption(16, false);
6540 // RlyFile = false; - don't alter this just for PrefDir changes
6541  bool FinishElement;
6542  Screen->Cursor = TCursor(-11); // Hourglass;
6543  if((ConstructPrefDir->PrefDirSize() != 1) || (ConstructPrefDir->GetFixedPrefDirElementAt(183, 0).HLoc != HLoc) ||
6544  (ConstructPrefDir->GetFixedPrefDirElementAt(184, 0).VLoc != VLoc))
6545  { // not same as start element
6546  if(ConstructPrefDir->GetNextPrefDirElement(1, HLoc, VLoc, FinishElement))
6547  {
6549  if(FinishElement)
6550  {
6551  ShowMessage("Preferred direction added");
6554  SetLevel1Mode(16);
6555  Screen->Cursor = TCursor(-2); // Arrow
6556  Utilities->CallLogPop(57);
6557  return;
6558  }
6559  else
6560  {
6563  }
6564  // set again since 1st time
6565  // PrefDir vector only had start element & Truncate wasn't enabled, also need
6566  // to do the checks for Loop & End for each element as it is added
6567  }
6568  }
6569  else // same as start element
6570  {
6573  SetLevel1Mode(121);
6574  Screen->Cursor = TCursor(-2); // Arrow
6575  Utilities->CallLogPop(1714);
6576  return;
6577  }
6578  Screen->Cursor = TCursor(-2); // Arrow
6579  Utilities->CallLogPop(58);
6580  return;
6581  }
6582 
6584  {
6585  TrainController->LogEvent("mbLeft + PrefDirSelecting");
6586  ClearandRebuildRailway(56); // to get rid of earlier rectangles
6587  SelectStartPair.first = HLoc;
6588  SelectStartPair.second = VLoc;
6589  }
6590 
6591  else if(Level1Mode == OperMode)
6592  {
6593  if((Level2OperMode == Operating) && CallingOnButton->Down && CallingOnButton->Enabled)
6594  {
6595  TrainController->LogEvent("mbLeft + Operating & CallingOnButton->Down");
6596  int Position;
6597  TTrackElement TrackElement;
6598  if(Track->FindNonPlatformMatch(2, HLoc, VLoc, Position, TrackElement))
6599  {
6600  if(TrackElement.TrackType != SignalPost)
6601  {
6602  CallingOnButton->Down = false;
6603 // InfoPanel->Visible = false; //dropped at v1.3.0, not sure what purpose intended to serve but don't want to lose the info panel as did with this here also added line below to reset
6605  Utilities->CallLogPop(59);
6606  return;
6607  }
6608  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
6609  {
6611  {
6613  x).LeadExitPos] == Position) && (TrackElement.Config[Track->TrackElementAt(429, TrainController->TrainVectorAt(28,
6615  {
6616  // found it!
6617 /*
6618  if(TrackElement.SpeedTag == 68)
6619  {
6620  Display->PlotOutput(0, (HLoc * 16), (VLoc * 16), RailGraphics->bm68CallingOn);
6621  }
6622  if(TrackElement.SpeedTag == 69)
6623  {
6624  Display->PlotOutput(1, (HLoc * 16), (VLoc * 16), RailGraphics->bm69CallingOn);
6625  }
6626  if(TrackElement.SpeedTag == 70)
6627  {
6628  Display->PlotOutput(2, (HLoc * 16), (VLoc * 16), RailGraphics->bm70CallingOn);
6629  }
6630  if(TrackElement.SpeedTag == 71)
6631  {
6632  Display->PlotOutput(3, (HLoc * 16), (VLoc * 16), RailGraphics->bm71CallingOn);
6633  }
6634  if(TrackElement.SpeedTag == 72)
6635  {
6636  Display->PlotOutput(4, (HLoc * 16), (VLoc * 16), RailGraphics->bm72CallingOn);
6637  }
6638  if(TrackElement.SpeedTag == 73)
6639  {
6640  Display->PlotOutput(5, (HLoc * 16), (VLoc * 16), RailGraphics->bm73CallingOn);
6641  }
6642  if(TrackElement.SpeedTag == 74)
6643  {
6644  Display->PlotOutput(6, (HLoc * 16), (VLoc * 16), RailGraphics->bm74CallingOn);
6645  }
6646  if(TrackElement.SpeedTag == 75)
6647  {
6648  Display->PlotOutput(7, (HLoc * 16), (VLoc * 16), RailGraphics->bm75CallingOn);
6649  }
6650 */
6651  Track->TrackElementAt(430, Position).CallingOnSet = true;
6652  Track->PlotSignal(13, Track->TrackElementAt(893, Position), Display);
6653 // added at v 1.3.0 in place of the above to ensure ground signals (as well as others) plot correctly for proceed
6654  // have to call after CallingOnSet becomes true & can't use TrackElement as that still has CallingOnSet false
6655  ClearandRebuildRailway(69); // added at v1.3.0 to replot route on element after PlotSignal above
6658  CallingOnButton->Down = false;
6660 
6661 // set an unrestricted route into the station (just to the first platform) from the stop signal (note that it may be last in an autosigs
6662 // route) but remove any single route elements first (can't reach here if constructing a route), else may try to extend a route that
6663 // has been removed (only a precaution, shouldn't cause any probs whether single route set or not)
6664  for(unsigned int x = 0; x < AllRoutes->AllRoutesSize(); x++)
6665  {
6666  if(AllRoutes->GetFixedRouteAt(192, x).PrefDirSize() == 1)
6667  {
6668  // only allow route element to be removed if not selected for a route start otherwise
6669  // StartSelectionRouteID will be set & will fail at convert
6671  {
6673  AllRoutes->RemoveRouteElement(21, PDE.HLoc, PDE.VLoc, PDE.GetELink());
6674  TrainController->LogEvent("SingleRouteElementRemovedDuringCallon, H = " + AnsiString(PDE.HLoc) + ", V = " +
6675  AnsiString(PDE.VLoc));
6676  }
6677  }
6678  }
6679 
6680 // find the correct entry in CallonVector - i.e. where Position == RouteStartEntry
6681  for(unsigned int x = 0; x < AllRoutes->CallonVector.size(); x++)
6682  {
6683  if(AllRoutes->CallonVector.at(x).RouteStartPosition == Position)
6684  { // found it
6685  if(!(AllRoutes->CallonVector.at(x).RouteOrPartRouteSet))
6686  // if RouteOrPartRouteSet false then set an unrestricted route into platform
6687  {
6688  bool PointsChanged = false;
6689  IDInt ReqPosRouteID(-1);
6690  TOneRoute *NewRoute = new TOneRoute;
6691  bool CallonTrue = true;
6692  bool ConsecSignalsRouteFalse = false;
6693  if(NewRoute->GetNonPreferredRouteStartElement(1,
6694  Track->TrackElementAt(841, AllRoutes->CallonVector.at(x).RouteStartPosition).HLoc,
6695  Track->TrackElementAt(842, AllRoutes->CallonVector.at(x).RouteStartPosition).VLoc, ConsecSignalsRouteFalse,
6696  CallonTrue))
6697  {
6698  if(NewRoute->GetNextNonPreferredRouteElement(1,
6699  Track->TrackElementAt(843, AllRoutes->CallonVector.at(x).PlatformPosition).HLoc,
6700  Track->TrackElementAt(844, AllRoutes->CallonVector.at(x).PlatformPosition).VLoc, ConsecSignalsRouteFalse,
6701  CallonTrue, ReqPosRouteID, PointsChanged))
6702  {
6703  if(!PointsChanged) // shouldn't be changed, something wrong if true so don't plot route
6704  {
6705  NewRoute->ConvertAndAddNonPreferredRouteSearchVector(3, ReqPosRouteID);
6706  ClearandRebuildRailway(67); // to plot the route (only finds one so won't call repeatedly)
6707  }
6708  }
6709  }
6710  delete NewRoute;
6711  }
6712  }
6713  }
6714 // InfoPanel->Visible = false;
6715  Utilities->CallLogPop(60);
6716  return;
6717  }
6718  }
6719  }
6720  }
6721  CallingOnButton->Down = false;
6723  Utilities->CallLogPop(61);
6724  return;
6725  }
6726 /* get 1st element, first check if selected points, not in existing route, & in RouteNotStarted mode
6727  if so, set all the flash values, Track->PointFlashFlag & start time, then exit for flasher to take over.
6728  If any of above conditions not met then treat as route selection, setting route flasher if
6729  route continuing.
6730 */
6731 
6732  if((Level2OperMode == Operating) || (Level2OperMode == PreStart)) // not 'else if' as both may apply
6733  // disallow route setting if paused
6734  {
6735  if(Level2OperMode == PreStart)
6736  {
6737  PointsFlashDuration = 0.0;
6740  }
6741  else
6742  {
6743  float TempSpeedVal = 1; // added for v2.3.0 to keep durations same as x1 values for slow speeds
6744  if(TTClockSpeed < 1)
6745  TempSpeedVal = TTClockSpeed;
6746  PointsFlashDuration = AllRoutes->PointsDelay * TempSpeedVal;
6749  }
6750  if(RouteMode == RouteNotStarted)
6751  {
6752  TrainController->LogEvent("mbLeft + RouteNotStarted");
6753  int Position;
6754  TTrackElement TrackElement;
6755  if(Track->FindNonPlatformMatch(3, HLoc, VLoc, Position, TrackElement))
6756  {
6757  if((TrackElement.TrackType == Points) && !(AllRoutes->TrackIsInARoute(1, Position, 0))
6759  // Flash selected points & changeover if appropriate
6760  // need !Track->PointFlashFlag to prevent another point being selected while another is flashing, & !Track->RouteFlashFlag
6761  // to ensure user only does one thing at a time
6762  {
6763  if(TrackElement.TrainIDOnElement > -1)
6764  {
6765  TrainController->StopTTClockMessage(1, "Can't change points under a train!");
6766  Utilities->CallLogPop(62);
6767  return;
6768  }
6769  PointFlash->SetScreenHVSource(1, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6770 
6771 /*
6772  This used to try to allow any linked trailing edges to cause both points to change, but no good if
6773  there are two adjacent crossovers, where both trailing edges are linked to two different points.
6774  The wrong link might be chosen. Also doubtful if applying a strict order of checks would work, since
6775  may be obscure configurations that would be wrong. This function bypasses the MatchingPoint check, which
6776  ensures that there are no obscure links. Hence better to stick with original.
6777 
6778  //check if trailing edge linked to another point trailing edge
6779  int DivergingPosition = TrackElement.Conn[1];
6780  TTrackElement DivergingElement = Track->TrackElementAt(431, TrackElement.Conn[1]);
6781  DivergingPointVectorPosition = -1;
6782  if((DivergingElement.TrackType == Points) &&
6783  ((DivergingElement.Conn[1] == Position) || (DivergingElement.Conn[3] == Position)))
6784  {
6785  if(AllRoutes->TrackIsInARoute(, DivergingPosition))
6786  {
6787  ShowMessage("Linked points Locked");
6788  }
6789  else DivergingPointVectorPosition = DivergingPosition;
6790  }
6791  else
6792  {
6793  DivergingPosition = TrackElement.Conn[3];
6794  DivergingElement = Track->TrackElementAt(432, TrackElement.Conn[3]);
6795  if((DivergingElement.TrackType == Points) &&
6796  ((DivergingElement.Conn[1] == Position) || (DivergingElement.Conn[3] == Position)))
6797  {
6798  if(AllRoutes->TrackIsInARoute(, DivergingPosition))
6799  {
6800  ShowMessage("Linked points locked");
6801  }
6802  else DivergingPointVectorPosition = DivergingPosition;
6803  }
6804  }
6805  Track->PointFlashFlag = true;
6806  PointFlashVectorPosition = Position;
6807  PointFlashStartTime = TrainController->TTClockTime;
6808  [close curly bracket - if include it matches earlier non-commented one!]
6809 */
6810  TTrackElement DivergingElement = Track->TrackElementAt(433, TrackElement.Conn[3]);
6811  int DivergingPosition = TrackElement.Conn[3];
6812  if((DivergingElement.TrackType == Points) && (DivergingElement.Conn[3] == Position) && (Track->MatchingPoint(1, Position,
6813  DivergingPosition))) // full match inc same attributes
6814  {
6815  if(AllRoutes->TrackIsInARoute(4, DivergingPosition, 0))
6816  {
6817  TrainController->StopTTClockMessage(2, "Linked points locked");
6818  }
6819  else
6820  {
6821  Track->PointFlashFlag = true;
6822  PointFlashVectorPosition = Position;
6823  DivergingPointVectorPosition = DivergingPosition;
6825  }
6826  }
6827  else // no matching point, just change this point
6828  {
6829  Track->PointFlashFlag = true;
6830  PointFlashVectorPosition = Position;
6833  }
6834  }
6835 
6836  else if(Track->IsLCAtHV(59, HLoc, VLoc) && !Track->PointFlashFlag && !Track->RouteFlashFlag)//level crossing added at v2.6.0 to allow manual LC changing
6837  {
6838  if(Track->GetInactiveTrackElementFromTrackMap(5, HLoc, VLoc).Attribute != 2) // 2 = LC changing state, can't click if changing
6839  {
6840  Track->LCChangeFlag = true;
6841  bool TrainPresent = false;
6842  if(Track->IsLCBarrierDownAtHV(4, HLoc, VLoc)) //if true then raise barriers
6843  {
6844  //first need to identify the LC in the BarriersDownVector
6845  int BDVectorPos = -1;
6846  if(Track->AnyLinkedBarrierDownVectorManual(1, HLoc, VLoc, BDVectorPos)) //looking for same position & manually closed
6847  { //this largely copied from ClockTimer2
6849  Track->BarriersDownVector.at(BDVectorPos).VLoc, TrainPresent)) //returns true for route or train, and TrainPresent true if train on LC
6850  {
6851  TTrack::TActiveLevelCrossing CLC = Track->BarriersDownVector.at(BDVectorPos);
6852  // check if have exceeded the allowance (3 minutes for a train having passed or 0 for not) and add it to the overall excess time
6853  TDateTime TempExcessLCDownTime;
6854  if(Track->BarriersDownVector.at(BDVectorPos).ReducedTimePenalty) //this set in ClockTimer2, relies on train being on LC for >= 1 second or won't
6855  { //get the 3 mins allowance - hard to imagine will pass in less than a second!
6856  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime - TDateTime(180.0 / 86400);
6857  }
6858  else
6859  {
6860  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime;
6861  }
6862  if(TempExcessLCDownTime > TDateTime(0))
6863  {
6864  TrainController->ExcessLCDownMins += (double(TempExcessLCDownTime) * 1440);
6865  }
6866  CLC.StartTime = TrainController->TTClockTime; // reset these 3 members
6869  Track->SetLinkedLevelCrossingBarrierAttributes(7, CLC.HLoc, CLC.VLoc, 2); // set attr to 2 for changing state
6870  Track->ChangingLCVector.push_back(CLC);
6871  Track->BarriersDownVector.erase(Track->BarriersDownVector.begin() + BDVectorPos);
6872  }
6873  }
6874  }
6875  else //lowering
6876  {
6877  //this largely copied from SetLCChangeValues
6878  TTrack::TActiveLevelCrossing ALC; //constructor sets ReducedTimePenalty to false
6879  ALC.HLoc = HLoc;
6880  ALC.VLoc = VLoc;
6882  ALC.BaseElementSpeedTag = TrackElement.SpeedTag;
6885  ALC.ConsecSignals = 2;
6886  Track->SetLinkedManualLCs(0, HLoc, VLoc); //this sets all linked LC ConsecSignals values to 2 for manually lowered - differs from SetLCChangeValues which uses the route type
6887  Track->SetLinkedLevelCrossingBarrierAttributes(6, HLoc, VLoc, 2);//set attr to 2 for changing state
6888  Track->ChangingLCVector.push_back(ALC);
6890  {
6891  AnsiString Message = AnsiString("This will open the level crossing manually (it will show in green).\n\nA manually opened"
6892  " level crossing must be manually closed, and as soon as possible to avoid time penalties.\n\n"
6893  "This message will not be shown again.");
6894  TrainController->StopTTClockMessage(93, Message);
6896  }
6897  }
6898  }
6899  }
6900  else // route start
6901  {
6902  if(AutoSigsFlag)
6903  {
6904  AutoRouteStartMarker->SetScreenHVSource(2, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6906  }
6907  else if(ConsecSignalsRoute)
6908  {
6909  SigRouteStartMarker->SetScreenHVSource(3, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6911  }
6912  else
6913  {
6914  NonSigRouteStartMarker->SetScreenHVSource(4, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6916  }
6917  if(PreferredRoute)
6918  {
6919  if(!Track->PointFlashFlag && !Track->RouteFlashFlag) // don't allow a route to start if a point changing or
6920  // another route building
6921  {
6922  ConstructRoute->ClearRoute(); // in case not empty though should be
6924  {
6925  if(AutoSigsFlag)
6927  else
6930  InfoPanel->Visible = true;
6931  if(Level2OperMode == PreStart)
6932  InfoPanel->Caption = "PRE-START: Select next route location";
6933  else
6934  InfoPanel->Caption = "OPERATING: Select next route location";
6935  }
6936  }
6937  Utilities->CallLogPop(63);
6938  return;
6939  }
6940  else // nonpreferred route
6941  {
6942  if(!Track->PointFlashFlag && !Track->RouteFlashFlag) // don't allow a route to start if a point changing or
6943  // another route building
6944  {
6945  ConstructRoute->ClearRoute(); // in case not empty though should be
6946  bool CallonFalse = false;
6947  if(ConstructRoute->GetNonPreferredRouteStartElement(0, HLoc, VLoc, ConsecSignalsRoute, CallonFalse))
6948  {
6951  InfoPanel->Visible = true;
6952  if(Level2OperMode == PreStart)
6953  InfoPanel->Caption = "PRE-START: Select next route location";
6954  else
6955  InfoPanel->Caption = "OPERATING: Select next route location";
6956  }
6957  }
6958  Utilities->CallLogPop(64);
6959  return;
6960  } // NonPreferred route
6961  } // TrackType != Points
6962  } // if(Track->FindNonPlatformMatch(HLoc, VLoc, Position, TrackElement))
6963  } // if(RouteMode == RouteNotStarted)
6964  else // RouteContinuing
6965  {
6966  TrainController->LogEvent("mbLeft + RouteContinuing");
6967  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
6970  AutoRouteStartMarker->PlotOriginal(14, Display); // if overlay not plotted will ignore
6971  SigRouteStartMarker->PlotOriginal(15, Display); // if overlay not plotted will ignore
6972  NonSigRouteStartMarker->PlotOriginal(16, Display); // if overlay not plotted will ignore
6973  Screen->Cursor = TCursor(-11); // Hourglass - also set to an hourglass when flashing, after found required
6974  // element, but this sets it to an hourglass while searching
6975  bool PointsChanged = false;
6976  if(PreferredRoute)
6977  {
6978  // route added to AllRoutes in GetNextRouteElement if valid
6979  // int ReqPosRouteNumber;
6981  ConstructRoute->ReqPosRouteID, PointsChanged))
6982  {
6983  Track->RouteFlashFlag = true;
6984  PreferredRouteFlag = true;
6985  float TempSpeedVal = 1; // added for v2.3.0 to keep durations same as x1 values for slow speeds
6986  if(TTClockSpeed < 1)
6987  TempSpeedVal = TTClockSpeed;
6988  if(Level2OperMode == PreStart)
6989  RouteFlashDuration = 0.0;
6990  else if(PointsChanged)
6991  RouteFlashDuration = AllRoutes->PointsDelay * TempSpeedVal;
6992  else
6993  RouteFlashDuration = AllRoutes->SignalsDelay * TempSpeedVal;
6994  ConstructRoute->SetRouteFlashValues(1, AutoSigsFlag, true); // true for ConsecSignalsRoute
6996  }
6997  else
6998  {
7000  }
7001  Screen->Cursor = TCursor(-2); // Arrow
7002  TrainController->BaseTime = TDateTime::CurrentDateTime();
7004  Utilities->CallLogPop(65);
7005  return;
7006  }
7007  else
7008  {
7009  bool CallonFalse = false;
7011  PointsChanged))
7012  {
7013  Track->RouteFlashFlag = true;
7014  PreferredRouteFlag = false;
7015  float TempSpeedVal = 1; // added for v2.3.0 to keep durations same as x1 values for slow speeds
7016  if(TTClockSpeed < 1)
7017  TempSpeedVal = TTClockSpeed;
7018  if(Level2OperMode == PreStart)
7019  RouteFlashDuration = 0.0;
7020  else if(PointsChanged)
7021  RouteFlashDuration = AllRoutes->PointsDelay * TempSpeedVal;
7022  else
7023  RouteFlashDuration = AllRoutes->SignalsDelay * TempSpeedVal;
7024  ConstructRoute->SetRouteFlashValues(2, false, false);
7026  }
7027  else
7028  {
7030  }
7031  }
7032  TrainController->BaseTime = TDateTime::CurrentDateTime();
7034  Screen->Cursor = TCursor(-2); // Arrow
7035  }
7036  Utilities->CallLogPop(66);
7037  return;
7038  }
7039  }
7040 
7041  Utilities->CallLogPop(68);
7042  }
7043  catch(const Exception &e)
7044  {
7045  ErrorLog(20, e.Message);
7046  }
7047 }
7048 
7049 // ---------------------------------------------------------------------------
7050 
7051 void TInterface::MainScreenMouseDown3(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
7052  // ZoomOut mode
7053 {
7054 // NB: DisplayZoomOutOffsetH & V take account of the Min & Max H & V values so don't need these again
7055  try
7056  {
7057  TrainController->LogEvent("MainScreenMouseDown3," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
7058  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",MainScreenMouseDown3," + AnsiString(Button) + "," + AnsiString(X) +
7059  "," + AnsiString(Y));
7060  if(Button != mbLeft)
7061  {
7062  // this routine new at v2.1.0. Allows railway moving for zoom-out mode
7065  WholeRailwayMoving = true;
7066  Screen->Cursor = TCursor(-22); // Four arrows;
7067  }
7068  else
7069  {
7070  InfoPanel->Visible = false; // reset infopanel in case not set later
7071  InfoPanel->Caption = "";
7072  int HRounding, VRounding;
7073  int TruePosH = (X / 4) + Display->DisplayZoomOutOffsetH;
7074  int TruePosV = (Y / 4) + Display->DisplayZoomOutOffsetV;
7075  // find nearest screen centre - from 30 to 210 horiz & from 18 to 126 vert
7076  if(TruePosH < 0)
7077  HRounding = -(Utilities->ScreenElementWidth / 4);
7078  else
7079  HRounding = (Utilities->ScreenElementWidth / 4);
7080  int CentreH = (((TruePosH + HRounding) / (Utilities->ScreenElementWidth / 2)) * (Utilities->ScreenElementWidth / 2));
7081  while((CentreH - Track->GetHLocMax()) >= (Utilities->ScreenElementWidth / 2))
7082  CentreH -= (Utilities->ScreenElementWidth / 2);
7083  while((Track->GetHLocMin() - CentreH) >= (Utilities->ScreenElementWidth / 2))
7084  CentreH += (Utilities->ScreenElementWidth / 2);
7085  if(TruePosV < 0)
7086  VRounding = -(Utilities->ScreenElementHeight / 4);
7087  else
7088  VRounding = (Utilities->ScreenElementHeight / 4);
7089  int CentreV = (((TruePosV + VRounding) / (Utilities->ScreenElementHeight / 2)) * (Utilities->ScreenElementHeight / 2));
7090  while((CentreV - Track->GetVLocMax()) >= (Utilities->ScreenElementHeight / 2))
7091  CentreV -= (Utilities->ScreenElementHeight / 2);
7092  while((Track->GetVLocMin() - CentreV) >= (Utilities->ScreenElementHeight / 2))
7093  CentreV += (Utilities->ScreenElementHeight / 2);
7094  Display->DisplayOffsetH = CentreH - (Utilities->ScreenElementWidth / 2);
7096 
7097  TLevel2OperMode TempLevel2OperMode = Level2OperMode;
7098  if(Level1Mode == BaseMode)
7099  SetLevel1Mode(17);
7100  else if(Level1Mode == TrackMode)
7101  {
7102  // set edit menu items
7104  PreventGapOffsetResetting = true; // when return from zoom by clicking screen don't force a return to the
7105  // displayed gap, user wants to display the clicked area
7106  SetLevel2TrackMode(32); // revert to earlier track mode from zoom
7107  PreventGapOffsetResetting = false;
7108  }
7109  else if(Level1Mode == PrefDirMode)
7110  {
7112  SetLevel2PrefDirMode(3); // revert to earlier PrefDir mode from zoom
7113  else
7114  SetLevel1Mode(33); // if PrefDirSelecting revert to normap PrefDirMode
7115  }
7116  // else if(Level1Mode == TrackMode) SetLevel1Mode();//just revert to basic track mode from zoom
7117  // else if(Level1Mode == PrefDirMode) SetLevel1Mode();//just revert to basic PrefDir mode from zoom
7118  else if(Level1Mode == TimetableMode)
7119  {
7120  InfoPanel->Visible = false;
7121  }
7122  // Not OperMode or RestartSessionOperMode as that resets the performance file
7123  else if(TempLevel2OperMode == Operating) // similar to SetLevel2OperMode but without resetting BaseTime
7124  {
7125  OperateButton->Enabled = true;
7126  OperateButton->Glyph->LoadFromResourceName(0, "PauseGraphic");
7127  ExitOperationButton->Enabled = true;
7129  }
7130  else if(TempLevel2OperMode == Paused) // similar to SetLevel2OperMode but without resetting RestartTime
7131  {
7132  OperateButton->Enabled = true;
7133  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
7134  ExitOperationButton->Enabled = true;
7135  TTClockAdjButton->Enabled = true;
7138  }
7139  else if(TempLevel2OperMode == PreStart)
7140  {
7141  OperateButton->Enabled = true;
7142  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
7143  ExitOperationButton->Enabled = true;
7144  TTClockAdjButton->Enabled = true;
7146  }
7147  Display->ZoomOutFlag = false; // reset this after level modes called so gap flash stays set if set to begin with
7150  }
7151  Utilities->CallLogPop(69);
7152  }
7153  catch(const Exception &e)
7154  {
7155  ErrorLog(21, e.Message);
7156  }
7157 }
7158 
7159 // ---------------------------------------------------------------------------
7160 
7161 void __fastcall TInterface::MainScreenMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
7162 {
7163  try
7164  {
7165  // TrainController->LogEvent("MainScreenMouseMove," + AnsiString(X) + "," + AnsiString(Y)); //dropped at v0.6, too many events
7166  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MainScreenMouseMove," + AnsiString(X) + "," + AnsiString(Y));
7167 
7168  if(!mbLeftDown && WholeRailwayMoving) // new at v2.1.0
7169  {
7170  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
7172  if(X < 0)
7173  X = 0; // ensure pointer stays within display area
7174  if(X > (MainScreen->Width - 1))
7175  X = MainScreen->Width - 1;
7176  if(Y < 0)
7177  Y = 0;
7178  if(Y > (MainScreen->Height - 1))
7179  Y = MainScreen->Height - 1;
7180 
7181  if(!Display->ZoomOutFlag)
7182  {
7183  int StartOffsetX = (X - StartWholeRailwayMoveHPos) % 16;
7184  int StartOffsetY = (Y - StartWholeRailwayMoveVPos) % 16;
7185  if((abs(X - StartWholeRailwayMoveHPos) >= 16) || (abs(Y - StartWholeRailwayMoveVPos) >= 16))
7186  {
7187  int NewH = X - StartWholeRailwayMoveHPos;
7188  int NewV = Y - StartWholeRailwayMoveVPos;
7189  Display->DisplayOffsetH -= NewH / 16;
7190  Display->DisplayOffsetV -= NewV / 16;
7191  StartWholeRailwayMoveHPos = X - StartOffsetX;
7192  StartWholeRailwayMoveVPos = Y - StartOffsetY;
7195  {
7197  }
7198  }
7199  }
7200 
7201  else
7202  {
7203  int StartZOffsetX = (X - StartWholeRailwayMoveHPos) % 4;
7204  int StartZOffsetY = (Y - StartWholeRailwayMoveVPos) % 4;
7205  if((abs(X - StartWholeRailwayMoveHPos) >= 4) || (abs(Y - StartWholeRailwayMoveVPos) >= 4))
7206  {
7207  int NewH = X - StartWholeRailwayMoveHPos;
7208  int NewV = Y - StartWholeRailwayMoveVPos;
7209  Display->DisplayZoomOutOffsetH -= NewH / 4;
7210  Display->DisplayZoomOutOffsetV -= NewV / 4;
7211  StartWholeRailwayMoveHPos = X - StartZOffsetX;
7212  StartWholeRailwayMoveVPos = Y - StartZOffsetY;
7213  Display->ClearDisplay(10);
7215  }
7216  }
7217  TrainController->BaseTime = TDateTime::CurrentDateTime();
7219  }
7220 
7221  else if(mbLeftDown)
7222  {
7224 /* [Repeated from MouseDown] - When 'select' chosen from the Edit menu (only available in 'AddTrack') conditions are set ready to enclose a rectangular screen area
7225  using MouseMove. When MouseDown occurs the starting point is marked (wrt whole railway, not just the screen) and stored in
7226  SelectStartPair. If the mouse button is released and a new start position selected then the earlier one is discarded. Providing the
7227  button is held down subsequent actions occur during MouseMove (to display the changing rectangle) and MouseUp to define the final
7228  selected rectangle.
7229  [New] At this point the select starting position has been defined in SelectStartPair, and the current mouse position is defined (wrt whole
7230  railway) in HLoc & VLoc from the screen positions X & Y by GetTrackLocsFromScreenPos. Both are incremented so that the rectangle
7231  includes the current point (if no mouse movement at all occurs then a 1 x 1 rectangle is displayed). Limits are set to prevent the
7232  displayed rectangle extending off screen. Edges are set at 60 & 36 rather than 59 & 35 because the defined rectangle excludes the
7233  rightmost and bottom HLoc & VLoc values, if 59 & 35 were used the right & bottom screen edges wouldn't be reached. A TRect is then
7234  defined from SelectStartPair and the HLoc/VLoc values, Clearand... called to clear earlier rectangles, and a dashed edge drawn round
7235  the selection.
7236 */
7237  {
7238  TrainController->LogEvent("MouseMove + TrackSelecting");
7239  int CurrentHLoc, CurrentVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7240  Track->GetTrackLocsFromScreenPos(2, CurrentHLoc, CurrentVLoc, X, Y);
7241  // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7242  // rightmost point and the VLoc value of the bottommost point
7243  if(CurrentHLoc >= StartHLoc)
7244  CurrentHLoc++;
7245  else
7246  StartHLoc++;
7247  if(CurrentVLoc >= StartVLoc)
7248  CurrentVLoc++;
7249  else
7250  StartVLoc++;
7251  if(CurrentHLoc - Display->DisplayOffsetH > Utilities->ScreenElementWidth)
7253  if(CurrentVLoc - Display->DisplayOffsetV > Utilities->ScreenElementHeight)
7255  if(CurrentHLoc - Display->DisplayOffsetH < 0)
7256  CurrentHLoc = Display->DisplayOffsetH;
7257  if(CurrentVLoc - Display->DisplayOffsetV < 0)
7258  CurrentVLoc = Display->DisplayOffsetV;
7259  TRect TempRect(StartHLoc, StartVLoc, CurrentHLoc, CurrentVLoc);
7260  ClearandRebuildRailway(14); // to clear earlier rectangles
7261  Display->PlotDashedRect(0, TempRect);
7262  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
7263  }
7264 
7266  {
7267  TrainController->LogEvent("MouseMove + PrefDirSelecting");
7268 
7269  int CurrentHLoc, CurrentVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7270  Track->GetTrackLocsFromScreenPos(5, CurrentHLoc, CurrentVLoc, X, Y);
7271  // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7272  // rightmost point and the VLoc value of the bottommost point
7273  if(CurrentHLoc >= StartHLoc)
7274  CurrentHLoc++;
7275  else
7276  StartHLoc++;
7277  if(CurrentVLoc >= StartVLoc)
7278  CurrentVLoc++;
7279  else
7280  StartVLoc++;
7281  if(CurrentHLoc - Display->DisplayOffsetH > Utilities->ScreenElementWidth)
7283  if(CurrentVLoc - Display->DisplayOffsetV > Utilities->ScreenElementHeight)
7285  if(CurrentHLoc - Display->DisplayOffsetH < 0)
7286  CurrentHLoc = Display->DisplayOffsetH;
7287  if(CurrentVLoc - Display->DisplayOffsetV < 0)
7288  CurrentVLoc = Display->DisplayOffsetV;
7289  TRect TempRect(StartHLoc, StartVLoc, CurrentHLoc, CurrentVLoc);
7290  ClearandRebuildRailway(57); // to clear earlier rectangles
7291  Display->PlotDashedRect(2, TempRect);
7292  Display->Update(); // need to keep this since Update() not called for PlotSmallOutput as too slow
7293  }
7294 
7296 /* [Repeated from MouseDown] - The same actions apply on MouseDown whether Copy or Cut selected from the menu. First the horizontal and vertical mouse position is
7297  checked and unless it lies within the selected rectangle and not within 4 pixels of an edge the pickup fails and the function returns.
7298  Otherwise flag SelectPickedUp is set to true (to allow it to move during MouseMove and remain in place at MouseUp) and the mouse position
7299  is saved in SelectBitmapMouseLocX & Y for use later in MouseMove & MouseUp.
7300  [New] - The same actions apply on MouseMove whether Copy or Cut selected from the menu. The X & Y mouse positions are checked and set to
7301  stay within the display area. Then the current selection H & V positions are stored in NewSelectBitmapHLoc & VLoc.
7302  These change continually while the mouse and the selection are moving, they are only read on MouseUp to retain the position that it then
7303  occupies. Clearand... is called finally to clear earlier selection displays.
7304 */
7305  {
7306  TrainController->LogEvent("MouseMove + Copy or CutMoving & SelectPickedUp");
7307  if(X < 0)
7308  X = 0; // ensure pointer stays within display area
7309  if(X > (MainScreen->Width - 1))
7310  X = MainScreen->Width - 1;
7311  if(Y < 0)
7312  Y = 0;
7313  if(Y > (MainScreen->Height - 1))
7314  Y = MainScreen->Height - 1;
7317  ClearandRebuildRailway(15); // plots SelectBitmap at the position given by NewSelectBitmapHLoc & ...VLoc
7318  }
7319 
7321  {
7322  TrainController->LogEvent("MouseMove + MoveTextOrGraphic & TextFoundFlag");
7324  NewHPos = TextOrUserGraphicGridVal * (div(NewHPos, TextOrUserGraphicGridVal).quot);
7326  NewVPos = TextOrUserGraphicGridVal * (div(NewVPos, TextOrUserGraphicGridVal).quot);
7327 
7328  TextHandler->TextPtrAt(26, TextItem)->HPos = NewHPos;
7329  TextHandler->TextPtrAt(27, TextItem)->VPos = NewVPos;
7331  }
7332 
7334  {
7335  TrainController->LogEvent("MouseMove + MoveTextOrGraphic & UserGraphicFoundFlag");
7337  NewHPos = TextOrUserGraphicGridVal * (div(NewHPos, TextOrUserGraphicGridVal).quot);
7339  NewVPos = TextOrUserGraphicGridVal * (div(NewVPos, TextOrUserGraphicGridVal).quot);
7340 
7344  }
7345  }
7346  Utilities->CallLogPop(70);
7347  }
7348  catch(const Exception &e)
7349  {
7350  ErrorLog(22, e.Message);
7351  }
7352 }
7353 
7354 // ---------------------------------------------------------------------------
7355 void __fastcall TInterface::MainScreenMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
7356 {
7357 /* [Repeated from MouseDown] - When 'select' chosen from the Edit menu (only available in 'AddTrack') conditions are set ready to enclose a rectangular screen area
7358  using MouseMove. When MouseDown occurs the starting point is marked (wrt whole railway, not just the screen) and stored in
7359  SelectStartPair. If the mouse button is released and a new start position selected then the earlier one is discarded. Providing the
7360  button is held down subsequent actions occur during MouseMove (to display the changing rectangle) and MouseUp to define the final
7361  selected rectangle.
7362  [Repeated from MouseMove] - At this point the select starting position has been defined in SelectStartPair, and the current mouse position is defined (wrt whole
7363  railway) in HLoc & VLoc from the screen positions X & Y by GetTrackLocsFromScreenPos. Both are incremented so that the rectangle
7364  includes the current point (if no mouse movement at all occurs then a 1 x 1 rectangle is displayed). Limits are set to prevent the
7365  displayed rectangle extending off screen. Edges are set at 60 & 36 rather than 59 & 35 because the defined rectangle excludes the
7366  rightmost and bottom HLoc & VLoc values, if 59 & 35 were used the right & bottom screen edges wouldn't be reached. A TRect is then
7367  defined from SelectStartPair and the HLoc/VLoc values, Clearand... called to clear earlier rectangles, and a dashed edge drawn round
7368  the selection.
7369  [New] This function can take some time so an houglass cursor is displayed. The rectangle is fully defined, so the final screen X & Y
7370  values are translated into HLoc & VLoc values (wrt whole railway) and SelectEndPair set using them. The rectangle can be defined in any
7371  direction, so the end points may be before or after the starting points for both horizontal and vertical directions. Therefore the
7372  rectangle that will be used subsequently - SelectRect - is defined from SelectStart and SelectEnd allowing for any direction. Screen
7373  limits are set as during MouseMove, and a dashed edge drawn as before. Then a check is made to see if the final rectangle has any area,
7374  and if not 'Select' mode is kept and the function ends so that a new rectangle can be drawn, otherwise new menu items Cut, Copy & Delete,
7375  are enabled. Now the SelectBitmap is made ready by filling with white prior to the track bitmaps being copied. If this isn't done the
7376  track bitmaps are loaded from the top left hand corner and the rest becomes black - not what is wanted! The SelectVector (defined in
7377  TrackUnit) is then loaded with the elements enclosed by the rectangle, top to bottom and left to right, active track elements first then
7378  inactive track elements. Empty squares are ignored as are default (erased) elements. Now the SelectVector is read and the corresponding
7379  element bitmaps transferred to SelectBitmap in the appropriate positions, then a dashed border added. Finally the cursor is changed back
7380  to an arrow.
7381 */
7382  try
7383  {
7384  TrainController->LogEvent("MainScreenMouseUp," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
7385  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MainScreenMouseUp," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
7386  WholeRailwayMoving = false; // added at v2.1.0
7387  Screen->Cursor = TCursor(-2); // Arrow; (to reset from four arrows when moving) added at v2.1.0
7389  {
7390  TrainController->LogEvent("MouseUp + TrackSelecting + mbLeftDown");
7391  Screen->Cursor = TCursor(-11); // Hourglass;
7392  int EndHLoc, EndVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7393  Track->GetTrackLocsFromScreenPos(3, EndHLoc, EndVLoc, X, Y); // these values don't allow for offsets so add in later
7394 // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7395 // rightmost point and the VLoc value of the bottommost point
7396  if(EndHLoc >= StartHLoc)
7397  EndHLoc++;
7398  else
7399  StartHLoc++;
7400  if(EndVLoc >= StartVLoc)
7401  EndVLoc++;
7402  else
7403  StartVLoc++;
7404  if(StartHLoc >= EndHLoc)
7405  {
7406  SelectRect.left = EndHLoc;
7407  SelectRect.right = StartHLoc;
7408  }
7409  else
7410  {
7411  SelectRect.left = StartHLoc;
7412  SelectRect.right = EndHLoc;
7413  }
7414  if(StartVLoc >= EndVLoc)
7415  {
7416  SelectRect.top = EndVLoc;
7417  SelectRect.bottom = StartVLoc;
7418  }
7419  else
7420  {
7421  SelectRect.top = StartVLoc;
7422  SelectRect.bottom = EndVLoc;
7423  }
7428  if(SelectRect.left - Display->DisplayOffsetH < 0)
7430  if(SelectRect.top - Display->DisplayOffsetV < 0)
7435  if((SelectRect.top == SelectRect.bottom) || (SelectRect.left == SelectRect.right))
7436  {
7437  SelectionValid = false;
7439  mbLeftDown = false;
7440  Screen->Cursor = TCursor(-2); // Arrow;
7441  Utilities->CallLogPop(71);
7442  return; // no rectangle
7443  }
7444  else
7445  {
7446  ReselectMenuItem->Enabled = false;
7447  CutMenuItem->Enabled = true;
7448  CopyMenuItem->Enabled = true;
7449  FlipMenuItem->Enabled = true;
7450  MirrorMenuItem->Enabled = true;
7451  RotRightMenuItem->Enabled = true;
7452  RotLeftMenuItem->Enabled = true;
7453  RotateMenuItem->Enabled = true;
7454  PasteMenuItem->Enabled = false;
7455 // PasteWithAttributesMenuItem->Enabled = false; //new menu item for v2.2.0 only enabled after cutting
7456  DeleteMenuItem->Enabled = true;
7457  if(Track->IsTrackFinished())
7458  SelectLengthsMenuItem->Enabled = true; // only permit if finished because reverts to DistanceStart
7459  else
7460  SelectLengthsMenuItem->Enabled = false; // and that can only be used if track linked
7461  SelectBiDirPrefDirsMenuItem->Visible = false;
7462  CancelSelectionMenuItem->Enabled = true;
7463  // set SelectBitmap
7464  SelectBitmap->Width = (SelectRect.right - SelectRect.left) * 16;
7465  SelectBitmap->Height = (SelectRect.bottom - SelectRect.top) * 16;
7466 
7467  // fill it with transparent white (i.e. use Draw) else graphics all plot from top left hand corner
7468  for(int H = 0; H < (SelectBitmap->Width) / 16; H++)
7469  {
7470  for(int V = 0; V < (SelectBitmap->Height) / 16; V++)
7471  {
7472  SelectBitmap->Canvas->Draw(H * 16, V * 16, RailGraphics->bmSolidBgnd);
7473  // NB in above if use bmTransparent it ISN'T transparent, but if use the non-transparent bmSolidBgnd it IS transparent
7474  // presumably superimposing a transparent bitmap onto a transparent bitmap makes the result non-transparent!
7475  }
7476  }
7477 
7478  // store elements in Track->SelectVector, active elements first then inactive so active element plotted first during paste
7479  // clear the vector first
7481  TTrackElement TempElement; // default element
7482  bool FoundFlag;
7483  for(int x = SelectRect.left; x < SelectRect.right; x++)
7484  {
7485  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
7486  {
7487  int ATVecPos = Track->GetVectorPositionFromTrackMap(2, x, y, FoundFlag);
7488  if(FoundFlag)
7489  {
7490  TempElement = Track->TrackElementAt(440, ATVecPos);
7491  if(TempElement.SpeedTag > 0)
7492  Track->SelectPush(TempElement); // don't store erase elements
7493  }
7494  }
7495  }
7496  // now store inactive elements
7497  for(int x = SelectRect.left; x < SelectRect.right; x++)
7498  {
7499  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
7500  {
7501  TTrack::TIMPair IATVecPair = Track->GetVectorPositionsFromInactiveTrackMap(2, x, y, FoundFlag);
7502  if(FoundFlag)
7503  {
7504  TempElement = Track->InactiveTrackElementAt(30, IATVecPair.first);
7505  Track->SelectPush(TempElement); // only want SpeedTag & location set, rest defaults
7506  if(IATVecPair.second != IATVecPair.first) // 2 elements stored at location, i.e. platforms
7507  {
7508  TempElement = Track->InactiveTrackElementAt(31, IATVecPair.second);
7509  Track->SelectPush(TempElement);
7510  }
7511  }
7512  }
7513  }
7514  // store text items
7515  int LowSelectHPos = SelectRect.left * 16;
7516  int HighSelectHPos = SelectRect.right * 16;
7517  int LowSelectVPos = SelectRect.top * 16;
7518  int HighSelectVPos = SelectRect.bottom * 16;
7519  TextHandler->SelectTextVector.clear();
7520  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
7521  {
7522  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr < TextHandler->TextVector.end(); TextPtr++)
7523  {
7524  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
7525  HighSelectVPos))
7526  {
7527  // have to create a new TextItem in order to create a new Font object
7528  // BUT: only create new items where they don't appear as named location names
7529  // in SelectVector, since those names shouldn't be copied or pasted.
7530  // NB: altered for PasteWithAttributes - at v2.2.0 save the named element but prefix it with "##**"
7531  // so can paste or not depending on which type of paste is being used (unlikely to use that in a real name)
7532  bool SelectVectorNamedElement = false;
7533  AnsiString SelectTextString; // new at v2.2.0
7534  for(unsigned int x = 0; x < Track->SelectVector.size(); x++)
7535  {
7536  if(Track->SelectVector.at(x).LocationName == TextPtr->TextString)
7537  {
7538  SelectVectorNamedElement = true;
7539  break;
7540  }
7541  }
7542  if(SelectVectorNamedElement) // changed at v2.2.0
7543  {
7544  SelectTextString = "##**" + TextPtr->TextString; // new at v2.2.0
7545  }
7546  else // new at v2.2.0
7547  {
7548  SelectTextString = TextPtr->TextString;
7549  }
7550  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
7551  TextHandler->SelectTextVector.push_back(TextItem); // changed at v2.2.0
7552  }
7553  }
7554  }
7555  // store graphic items, but first clear SelectGraphicVector
7556  Track->SelectGraphicVector.clear();
7557  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
7558  {
7559  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = Track->UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
7560  UserGraphicPtr++)
7561  {
7562  if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) &&
7563  (UserGraphicPtr->VPos >= LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
7564  {
7565  Track->SelectGraphicVector.push_back(*UserGraphicPtr);
7566  }
7567  }
7568  }
7569 // new method - direct copying of existing selection so text included
7570  TRect Dest(0, 0, SelectBitmap->Width, SelectBitmap->Height);
7571  TRect Source(((SelectRect.left - Display->DisplayOffsetH) * 16), ((SelectRect.top - Display->DisplayOffsetV) * 16),
7572  ((SelectRect.right - Display->DisplayOffsetH) * 16), ((SelectRect.bottom - Display->DisplayOffsetV) * 16));
7573  SelectBitmap->Canvas->CopyRect(Dest, MainScreen->Canvas, Source);
7574  SelectionValid = true;
7575  }
7576  Screen->Cursor = TCursor(-2); // Arrow;
7577  }
7578 
7580  {
7581  TrainController->LogEvent("MouseUp + PrefDirSelecting + mbLeftDown");
7582  Screen->Cursor = TCursor(-11); // Hourglass;
7583 
7584  int EndHLoc, EndVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7585  Track->GetTrackLocsFromScreenPos(6, EndHLoc, EndVLoc, X, Y); // these values don't allow for offsets so add in later
7586 // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7587 // rightmost point and the VLoc value of the bottommost point
7588  if(EndHLoc >= StartHLoc)
7589  EndHLoc++;
7590  else
7591  StartHLoc++;
7592  if(EndVLoc >= StartVLoc)
7593  EndVLoc++;
7594  else
7595  StartVLoc++;
7596  if(StartHLoc >= EndHLoc)
7597  {
7598  SelectRect.left = EndHLoc;
7599  SelectRect.right = StartHLoc;
7600  }
7601  else
7602  {
7603  SelectRect.left = StartHLoc;
7604  SelectRect.right = EndHLoc;
7605  }
7606  if(StartVLoc >= EndVLoc)
7607  {
7608  SelectRect.top = EndVLoc;
7609  SelectRect.bottom = StartVLoc;
7610  }
7611  else
7612  {
7613  SelectRect.top = StartVLoc;
7614  SelectRect.bottom = EndVLoc;
7615  }
7620  if(SelectRect.left - Display->DisplayOffsetH < 0)
7622  if(SelectRect.top - Display->DisplayOffsetV < 0)
7627  if((SelectRect.top == SelectRect.bottom) || (SelectRect.left == SelectRect.right))
7628  {
7630  mbLeftDown = false;
7631  Screen->Cursor = TCursor(-2); // Arrow;
7632  Utilities->CallLogPop(1551);
7633  return; // no rectangle
7634  }
7635  else
7636  {
7637  SelectBiDirPrefDirsMenuItem->Enabled = true;
7638  CancelSelectionMenuItem->Enabled = true;
7639  // don't need SelectBitmap for PrefDir selection
7640 
7641  // store active elements in Track->SelectVector, ignore inactive elements
7642  // clear the vector first
7644  TTrackElement TempElement; // default element
7645  bool FoundFlag;
7646  for(int x = SelectRect.left; x < SelectRect.right; x++)
7647  {
7648  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
7649  {
7650  int ATVecPos = Track->GetVectorPositionFromTrackMap(43, x, y, FoundFlag);
7651  if(FoundFlag)
7652  {
7653  TempElement = Track->TrackElementAt(729, ATVecPos);
7654  if(TempElement.SpeedTag > 0)
7655  Track->SelectPush(TempElement); // don't store erase elements
7656  }
7657  }
7658  }
7659  }
7660  Screen->Cursor = TCursor(-2); // Arrow;
7661  }
7662 
7664 /* [Repeated from MouseDown] - The same actions apply on MouseDown whether Copy or Cut selected from the menu. First the horizontal and vertical mouse position is
7665  checked and unless it lies within the selected rectangle and not within 4 pixels of an edge the pickup fails and the function returns.
7666  Otherwise flag SelectPickedUp is set to true (to allow it to move during MouseMove and remain in place at MouseUp) and the mouse position
7667  is saved in SelectBitmapMouseLocX & Y for use later in MouseMove & MouseUp.
7668  [Repeated from MouseMove] - The same actions apply on MouseMove whether Copy or Cut selected from the menu. The X & Y mouse positions are checked and set to
7669  stay within the display area. Then the current selection H & V positions are stored in NewSelectBitmapHLoc & VLoc.
7670  These change continually while the mouse and the selection are moving, they are only read on MouseUp to retain the position that it then
7671  occupies. Clearand... is called finally to clear earlier selection displays.
7672  [New] - The only action here is to transfer the values of NewSelectBitmapHLoc & VLoc to SelectBitmapHLoc & VLoc so that the selection
7673  stays in the same position (Clearand... checks whether the mouse is moving (both mbLeftDown & SelectPickedUp true) or stopped (either
7674  mbLeftDown or SelectPickedUp false) and uses NewSelectBitmapHLoc & VLoc or SelectBitmapHLoc & SelectBitmapVLoc respectively.
7675 */
7676  {
7677  TrainController->LogEvent("MouseUp + Copy or CutMoving + mbLeftDown + SelectPickedUp");
7680  }
7681 
7682  mbLeftDown = false;
7683  Track->CalcHLocMinEtc(11);
7684  Utilities->CallLogPop(72);
7685  }
7686  catch(const Exception &e)
7687  {
7688  ErrorLog(23, e.Message);
7689  }
7690 }
7691 
7692 // ---------------------------------------------------------------------------
7693 
7694 void __fastcall TInterface::MasterClockTimer(TObject *Sender)
7695 {
7696  try
7697  {
7698  // don't call LogEvent here as would occur too often
7699  // have to allow in zoomout mode
7700  if(ErrorLogCalledFlag)
7701  return; // don't continue after an error
7702 
7703  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MasterClockTimer");
7704  // put counter outside Clock2 as that may be missed
7705  LCResetCounter++;
7706 // this checks LCs every 20 clock ticks (1 sec) & raises barriers if no route & no train present, to avoid delays due to too frequent calls
7707  if(LCResetCounter > 19)
7708  LCResetCounter = 0;
7710  if(WarningFlashCount > 4)
7711  WarningFlashCount = 0;
7712  if(WarningFlashCount == 0)
7713  {
7715  }
7716 
7717  if(Utilities->CallLog.size() > 50) // use CTRL ALT 2 to see CallLogSize as program operates
7718  {
7719  throw Exception("Warning - Utilities->CallLog contains more than 50 items"); // check before clock stopped
7720  }
7721 
7723  // stopped during 'Paused', when modal windows appear - Popup menu & ShowMessage, and at other times
7724  {
7725  // RestartTime is TTClockTime when operation pauses (timetable start time initially),
7726  // BaseTime is CurrentDateTime() when operation restarts
7727 
7728 // clock speed multiplier
7729  double RealTimeDouble = double(TDateTime::CurrentDateTime() - TrainController->BaseTime);
7730  TrainController->TTClockTime = TDateTime(TTClockSpeed * RealTimeDouble) + TrainController->RestartTime;
7731 // TrainController->TTClockTime = TDateTime::CurrentDateTime() - TrainController->BaseTime + TrainController->RestartTime;
7732  }
7733 
7734  TotalTicks++;
7736  {
7737  MissedTicks++;
7738  Utilities->CallLogPop(774);
7739  return;
7740  }
7741  Utilities->Clock2Stopped = true; //don't allow overlapping calls
7742  ClockTimer2(0);
7743  Utilities->Clock2Stopped = false;
7744  Utilities->CallLogPop(73);
7745  }
7746  catch(const Exception &e)
7747  {
7748  ErrorLog(24, e.Message);
7749  }
7750 }
7751 
7752 // ---------------------------------------------------------------------------
7753 
7754 void TInterface::ClockTimer2(int Caller)
7755 {
7756 // called every 50mSec
7757  try
7758  {
7759  // have to allow in zoomout mode
7760  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ClockTimer2");
7761 
7762  // dropped at 2.0.0 because RestoreFocusPanel->SetFocus(); hides the help screen
7763  // If a button holds focus then all that is needed is to click the screen and the arrow keys work correctly
7764 
7765 /* Dropped when new .chm help file introduced at v2.0.0 - this hid it after ~20ms. Replaced by a new section in
7766  MainScreenMouseDown where focus restored to screen when click anywhere on screen, allowing navigation keys to
7767  move screen when clicked if focus had been captured by another panel when these keys just cycle through the panel buttons
7768 
7769  bool FocusRestoreAllowedFlag = true; //added at v1.3.0
7770 
7771  if(TextBox->Focused() || DistanceBox->Focused() || SpeedLimitBox->Focused() || LocationNameTextBox->Focused() || MileEdit->Focused() || ChainEdit->Focused() || YardEdit->Focused() ||
7772  SpeedEditBox2->Focused() || LocationNameComboBox->Focused() || AddSubMinsBox->Focused() || SpeedEditBox->Focused() || PowerEditBox->Focused() || OneEntryTimetableMemo->Focused() ||
7773  AddPrefDirButton->Focused()) //Added at v1.3.0. If any of these has focus then they keep it until they release it. AddPrefDirButton is included as it should keep focus
7774  FocusRestoreAllowedFlag = false; //when it has it - eases the setting of PrefDirs, also this button becomes disabled after use so focus returns to Interface naturally
7775 
7776  if(!Focused() && FocusRestoreAllowedFlag && (GetAsyncKeyState(VK_LBUTTON) >= 0) && (GetAsyncKeyState(VK_RBUTTON) >= 0)) //condition added at v1.3.0 to ensure focus returned to
7777  //Interface (so arrow keys work to move screen) & not left at any of the buttons or other Windows controls
7778  //include the Windows API functions to test that the mouse buttons are not down (strictly only need left but user may have mapped the left onto the right so test both) - if not
7779  //tested then don't always respond to button clicks on navigation and other buttons because the focus can be grabbed back from the button by RestoreFocusPanel before the button
7780  //can respond (takes about 200mSec from click to response) a delay is also included to doubly avoid the button losing focus as above
7781  {
7782  ClockTimer2Count++; //doesn't matter what value it starts at on first use, it will soon revert to 0
7783  if(ClockTimer2Count > 10) ClockTimer2Count = 0; //half second delay
7784  if(ClockTimer2Count == 0)
7785  {
7786  RestoreFocusPanel->Visible = true;
7787  RestoreFocusPanel->Enabled = true;
7788  RestoreFocusPanel->BringToFront();
7789  //RestoreFocusPanel->SetFocus(); //to remove focus from anything else
7790  RestoreFocusPanel->Enabled = false; //to remove focus from RestoreFocusPanel & return it to Interface
7791  RestoreFocusPanel->Visible = false;
7792  }
7793  }
7794  else ClockTimer2Count = 0; //reset to 0 so ensure full delay occurs before RestoreFocusPanel grabs focus from anything else
7795 */
7796 
7797  CallLogTickerLabel->Caption = Utilities->CallLog.size(); // diagnostic test function to ensure all CallLogs are popped - visibility
7798  // toggled by 'Ctrl Alt 2' when Interface form has focus
7799 
7800  // set current time
7801  TDateTime Now = TrainController->TTClockTime;
7802 
7807 
7808  if(OperatorActionPanel->Visible)
7812  TrainController->OpActionPanelHintDelayCounter = 60; // new at v2.2.0
7813 
7814  TrainController->RandomFailureCounter++; // new at v2.4.0 counts up for 53 seconds then resets
7816  {
7818  }
7819 
7820 // Update Displayed Clock - resets to 0 at 96hours
7822 
7823 // Below added at v2.1.0 to ensure WholeRailwayMoving flag reset when not moving (when rh mouse button up) as sometimes misses
7824 // MouseUp events, probably due to a clash between a moving event and a mouse up event. Note that checks that both mouse buttons are up because
7825 // function only checks the physical buttons, not the logical buttons. Most sig bit of return value set form key down.
7826  if(WholeRailwayMoving && (GetAsyncKeyState(VK_LBUTTON) >= 0) && (GetAsyncKeyState(VK_RBUTTON) >= 0))
7827  {
7828  WholeRailwayMoving = false;
7829  Screen->Cursor = TCursor(-2); // Arrow
7830  }
7831 
7832 // save session if required
7833  if(SaveSessionFlag)
7834  {
7835  SaveSession(0);
7836  SaveSessionFlag = false;
7837  }
7838 // load session if required
7839  if(LoadSessionFlag)
7840  {
7841  if(ClearEverything(3))
7842  {
7843  LoadSession(0);
7844  }
7845  LoadSessionFlag = false;
7846  }
7847 
7848 // check if any LCs need barriers raising
7849 
7851  {
7853  {
7854  for(int x = Track->BarriersDownVector.size() - 1; x >= 0; x--) //iterate downwards because erase element
7855  {
7856  bool TrainPresent = false;
7858  TrainPresent)) //returns true for route or train, and TrainPresent true if train on LC
7859  {
7860  if(TrainPresent)
7861  {
7862  Track->BarriersDownVector.at(x).ReducedTimePenalty = true; //to allow 3 mins before time penalty starts to clock up, if no train passes then no time allowance
7863  }
7864  }
7865  else
7866  {
7867  if(Track->BarriersDownVector.at(x).ConsecSignals != 2) //added at v2.6.0 for manual LC operation
7868  {
7869  Track->LCChangeFlag = true;
7871  // check if have exceeded the allowance (3 minutes for a train having passed or 0 for not) and add it to the overall excess time
7872  TDateTime TempExcessLCDownTime;
7873  if(Track->BarriersDownVector.at(x).ReducedTimePenalty)
7874  {
7875  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime - TDateTime(180.0 / 86400);
7876  }
7877  else
7878  {
7879  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime;
7880  }
7881  if(TempExcessLCDownTime > TDateTime(0))
7882  TrainController->ExcessLCDownMins += (double(TempExcessLCDownTime) * 1440);
7883 
7884  CLC.StartTime = TrainController->TTClockTime; // reset these 3 members
7887  Track->SetLinkedLevelCrossingBarrierAttributes(0, CLC.HLoc, CLC.VLoc, 2); // set attr to 2 for changing state
7888  Track->ChangingLCVector.push_back(CLC);
7889  Track->BarriersDownVector.erase(Track->BarriersDownVector.begin() + x);
7890  }
7891  }
7892  }
7893  }
7894  }
7895 // clear LCChangeFlag if no LCs changing
7896  if(Track->ChangingLCVector.empty())
7897  {
7898  Track->LCChangeFlag = false;
7899  }
7900 
7901 // remove any single route elements if operating, but only if not constructing a route, else if extending the single route
7902 // element it may be removed prior to conversion & cause an error
7903 
7904 // note that if a train enters at a continuation and a signal is next but one to the continuation then the route element at that
7905 // signal won't be removed because the train's LagElement is still -1 and trains only remove route elements when LagElement is > -1.
7906 // This also means that a preferred route can't be cancelled as it's under a train, but it's probably not worth adding a patch just for
7907 // this, it shouldn't interfere with operation.
7909  {
7910  bool ElementRemovedFlag = false; // introduced at v0.6 to avoid calling Clearand.... multiple times
7911  for(unsigned int x = 0; x < AllRoutes->AllRoutesSize(); x++)
7912  {
7913  if(AllRoutes->GetFixedRouteAt(187, x).PrefDirSize() == 1)
7914  {
7915  // only allow route element to be removed if not selected for a route start otherwise StartSelectionRouteID will be
7916  // set & will fail at convert
7918  {
7920  AllRoutes->RemoveRouteElement(20, PDE.HLoc, PDE.VLoc, PDE.GetELink());
7921  ElementRemovedFlag = true;
7922  TrainController->LogEvent("SingleRouteElementRemoved, H = " + AnsiString(PDE.HLoc) + ", V = " + AnsiString(PDE.VLoc));
7923  }
7924  }
7925  }
7926  if(!Display->ZoomOutFlag && ElementRemovedFlag)
7927  {
7929  }
7930  // if zoomed out ignore, will display correctly when zoom in
7931  // if leave the Zoomout condition out then the zoom out will spontaneously cancel and the track won't display because
7932  // PlotOutput returns if zoomed out, and the zoom out flag isn't reset until the end of Clearand.....
7933  // this was moved outside the for.. next.. loop in v0.6 as it could be called multiple times and slowed down operation (noticeable with a fast clock)
7934  }
7935 // stop clock if hover over a warning
7936  bool WH1 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog1->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog1->Width + OutputLog1->Left))
7937  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog1->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog1->Height + OutputLog1->Top))
7938  && OutputLog1->Caption != "";
7939  bool WH2 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog2->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog2->Width + OutputLog2->Left))
7940  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog2->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog2->Height + OutputLog2->Top))
7941  && OutputLog2->Caption != "";
7942  bool WH3 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog3->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog3->Width + OutputLog3->Left))
7943  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog3->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog3->Height + OutputLog3->Top))
7944  && OutputLog3->Caption != "";
7945  bool WH4 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog4->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog4->Width + OutputLog4->Left))
7946  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog4->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog4->Height + OutputLog4->Top))
7947  && OutputLog4->Caption != "";
7948  bool WH5 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog5->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog5->Width + OutputLog5->Left))
7949  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog5->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog5->Height + OutputLog5->Top))
7950  && OutputLog5->Caption != "";
7951  bool WH6 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog6->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog6->Width + OutputLog6->Left))
7952  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog6->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog6->Height + OutputLog6->Top))
7953  && OutputLog6->Caption != "";
7954  bool WH7 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog7->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog7->Width + OutputLog7->Left))
7955  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog7->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog7->Height + OutputLog7->Top))
7956  && OutputLog7->Caption != "";
7957  bool WH8 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog8->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog8->Width + OutputLog8->Left))
7958  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog8->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog8->Height + OutputLog8->Top))
7959  && OutputLog8->Caption != "";
7960  bool WH9 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog9->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog9->Width + OutputLog9->Left))
7961  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog9->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog9->Height + OutputLog9->Top))
7962  && OutputLog9->Caption != "";
7963  bool WH10 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog10->Left) &&
7964  (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog10->Width + OutputLog10->Left)) && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog10->Top) &&
7965  (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog10->Height + OutputLog10->Top)) && OutputLog10->Caption != "";
7966 
7967  if(WH1 || WH2 || WH3 || WH4 || WH5 || WH6 || WH7 || WH8 || WH9 || WH10)
7968  {
7969  if(!WarningHover)
7970  {
7971  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
7973  WarningHover = true;
7974  }
7975  }
7976  else if(WarningHover)
7977  {
7978  WarningHover = false;
7979  TrainController->BaseTime = TDateTime::CurrentDateTime();
7981  }
7982 
7983 // development panel - visibility toggled by 'Ctrl Alt 3' when Interface form has focus
7984  if(DevelopmentPanel->Visible)
7985  {
7986  int Position;
7987  TTrackElement TrackElement;
7988  AnsiString Type[15] =
7989  {"Simple", "Crossover", "Points", "Buffers", "Bridge", "SignalPost", "Continuation", "Platform", "GapJump", "FootCrossing", "Unused", "Concourse",
7990  "Parapet", "NamedNonStationLocation", "Erase"};
7991 
7992  int ScreenX = Mouse->CursorPos.x - MainScreen->ClientOrigin.x;
7993  int ScreenY = Mouse->CursorPos.y - MainScreen->ClientOrigin.y;
7994  int HLoc, VLoc;
7995  AnsiString MouseStr = "Posx: " + AnsiString(ScreenX) + "; Posy: " + AnsiString(ScreenY);
7996  DevelopmentPanel->Caption = CurDir + " " + MouseStr;
7997  Track->GetTrackLocsFromScreenPos(7, HLoc, VLoc, ScreenX, ScreenY);
7998  if(Track->FindNonPlatformMatch(1, HLoc, VLoc, Position, TrackElement))
7999  {
8000  DevelopmentPanel->Caption = MouseStr + "; TVPos: " + AnsiString(Position) + "; H: " + AnsiString(HLoc) + "; V: " + AnsiString(VLoc) +
8001  "; SpTg: " + AnsiString(TrackElement.SpeedTag) + "; Type: " + Type[TrackElement.TrackType] + "; Att: " + AnsiString(TrackElement.Attribute)
8002  + "; TrID: " + AnsiString(TrackElement.TrainIDOnElement) + "; TrID01: " + AnsiString(TrackElement.TrainIDOnBridgeTrackPos01) +
8003  "; TrID23: " + AnsiString(TrackElement.TrainIDOnBridgeTrackPos23) + "; " + TrackElement.LocationName + "; " +
8004  TrackElement.ActiveTrackElementName;
8005 // + "; OAHintCtr: " + TrainController->OpActionPanelHintDelayCounter;
8006  }
8007  }
8008 
8009  if(Level1Mode == TimetableMode)
8010  {
8011 /*These are for Shift Key shortcuts. Unless 'Click()' execution occurs after the key is pressed Windows stores the key until after any code is executed then selects
8012 the timetable entry that begins with the letter corresponding to the key. See DevHistory.txt for the version after v2.4.3 for details.
8013 
8014 First make sure the selected entry is the Highlighted entry, but only if both mouse buttons are up, to make sure AllEntriesTTListBoxMouseUp runs first or TopIndex
8015 likely to be set to the wrong position since when ...Selected... runs it sets TopIndex accordingly. Then when ...MouseUp runs it will use the wrong value and select
8016 the entry that the mouse is now on rather than the one that was chosen.
8017 Later addition: Set member variable AllEntriesTTListBox->TopIndex here if any flag set so when Copy or any other key function runs the top index is correct
8018 */
8019  if((GetKeyState(VK_LBUTTON) >= 0) && (GetKeyState(VK_RBUTTON) >= 0) && (TTCurrentEntryPtr > 0)) //high order bit set to 1 when button down, so arithmetically it is negative
8020  { //TTCurrentEntryPtr == 0 when create a timetable
8021  AllEntriesTTListBox->Selected[TTCurrentEntryPtr - TimetableEditVector.begin()] = true;
8022  }
8023  if(AnyTTKeyFlagSet()) //true if any of the below flags set
8024  {
8025  AllEntriesTTListBox->TopIndex = AllEntriesTTListBoxTopPosition; //reset it to the value before the key press changes it (see FormKeyDown)
8026  }
8028  {
8029  PreviousTTEntryButton->Click();
8030  SetTopIndex(0);
8031  PreviousTTEntryKeyFlag = false;
8032  }
8033  else if(NextTTEntryKeyFlag)
8034  {
8035  NextTTEntryButton->Click();
8036  SetTopIndex(1);
8037  NextTTEntryKeyFlag = false;
8038  }
8039  else if(MoveTTEntryUpKeyFlag)
8040  {
8041  MoveTTEntryUpButton->Click();
8042  SetTopIndex(2);
8043  MoveTTEntryUpKeyFlag = false;
8044  }
8045  else if(MoveTTEntryDownKeyFlag)
8046  {
8047  MoveTTEntryDownButton->Click();
8048  SetTopIndex(3);
8049  MoveTTEntryDownKeyFlag = false;
8050  }
8051  else if(CopyTTEntryKeyFlag)
8052  {
8053  CopyTTEntryButton->Click();
8054  SetTopIndex(4);
8055  CopyTTEntryKeyFlag = false;
8056  }
8057  else if(CutTTEntryKeyFlag)
8058  {
8059  CutTTEntryButton->Click();
8060  SetTopIndex(5);
8061  CutTTEntryKeyFlag = false;
8062  }
8063  else if(PasteTTEntryKeyFlag)
8064  {
8065  PasteTTEntryButton->Click();
8066  SetTopIndex(6);
8067  PasteTTEntryKeyFlag = false;
8068  }
8069  else if(DeleteTTEntryKeyFlag)
8070  {
8071  DeleteTTEntryButton->Click();
8072  SetTopIndex(7);
8073  DeleteTTEntryKeyFlag = false;
8074  }
8075  else if(NewTTEntryKeyFlag)
8076  {
8077  NewTTEntryButton->Click();
8078  SetTopIndex(8);
8079  NewTTEntryKeyFlag = false;
8080  }
8081  else if(AZOrderKeyFlag)
8082  {
8083  AZOrderButton->Click();
8084  SetTopIndex(9);
8085  AZOrderKeyFlag = false;
8086  }
8088  {
8089  TTServiceSyntaxCheckButton->Click();
8090  SetTopIndex(12);
8092  }
8093  else if(ValidateTimetableKeyFlag)
8094  {
8095  ValidateTimetableButton->Click();
8096  SetTopIndex(13);
8097  ValidateTimetableKeyFlag = false;
8098  }
8099  else if(SaveTTKeyFlag)
8100  {
8101  SaveTTButton->Click();
8102  SetTopIndex(14);
8103  SaveTTKeyFlag = false;
8104  }
8105  else if(SaveTTAsKeyFlag)
8106  {
8107  SaveTTAsButton->Click();
8108  SetTopIndex(15);
8109  SaveTTAsKeyFlag = false;
8110  }
8111  else if(RestoreTTKeyFlag)
8112  {
8113  RestoreTTButton->Click();
8114  SetTopIndex(16);
8115  RestoreTTKeyFlag = false;
8116  }
8117  else if(ExportTTKeyFlag)
8118  {
8119  ExportTTButton->Click();
8120  SetTopIndex(17);
8121  ExportTTKeyFlag = false;
8122  }
8123  else if(ConflictAnalysisKeyFlag)
8124  {
8125  ConflictAnalysisButton->Click();
8126  SetTopIndex(18);
8127  ConflictAnalysisKeyFlag = false;
8128  }
8129 
8130 
8131 // highlight timetable entry if in tt mode (have to call this regularly so will scroll with the listbox)
8132  if(!TimetableEditVector.empty() && (TTCurrentEntryPtr > 0))
8133  {
8135  }
8136  else
8137  {
8139  }
8140  }
8141 
8142 // set cursor
8144  {
8145  if(!TempCursorSet)
8146  {
8147  TempCursor = Screen->Cursor;
8148  TempCursorSet = true;
8149  }
8150  Screen->Cursor = TCursor(-11); // Hourglass
8151  }
8152  else
8153  {
8154  if(TempCursorSet)
8155  {
8156  Screen->Cursor = TempCursor;
8157  TempCursorSet = false;
8158  }
8159  }
8160 
8161  if(Level2OperMode == Operating)
8162  {
8163  TrainController->Operate(0); // ensure this called AFTER the single element route removal to ensure any single elements removed
8164  // prior to CallingOnAllowed being called (in UpdateTrain) as that sets a route from the stop signal
8166  {
8167  UpdateOperatorActionPanel(0); // new at v2.2.0 to update panel when train OpTimeToAct updated (updated earlier)
8168  }
8169  TrainController->SignallerTrainRemovedOnAutoSigsRoute = false; // added at v1.3.0 to ensure doesn't persist beyond one call
8170  }
8171 
8172  else if(Level2OperMode == Paused) //added after v2.4.3 to show actions due after a session file reloaded
8173  {
8175  {
8176  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
8177  {
8179  }
8182  }
8183  }
8184 
8185 // plot trains in ZoomOut mode & flash trains where attention needed alternately on & off at each call
8186 // by examining Flash
8187  if((Level1Mode == OperMode) && (Display->ZoomOutFlag))
8188  {
8190  }
8191 
8192 // Deal with any flashing graphics
8194  {
8195  FlashingGraphics(0, Now); // only call when WarningFlash changes
8196  if(Level1Mode == OperMode)
8197  {
8198  if(WarningFlash)
8199  {
8201  {
8202  CrashImage->Visible = true;
8203  }
8205  {
8206  DerailImage->Visible = true;
8207  }
8209  {
8210  SPADImage->Visible = true;
8211  }
8213  {
8214  TrainFailedImage->Visible = true;
8215  }
8217  {
8218  CallOnImage->Visible = true;
8219  }
8221  {
8222  SignalStopImage->Visible = true;
8223  }
8225  {
8226  BufferAttentionImage->Visible = true;
8227  }
8228  }
8229  else
8230  {
8231  CrashImage->Visible = false;
8232  DerailImage->Visible = false;
8233  SPADImage->Visible = false;
8234  TrainFailedImage->Visible = false;
8235  CallOnImage->Visible = false;
8236  SignalStopImage->Visible = false;
8237  BufferAttentionImage->Visible = false;
8238  }
8239  }
8240  else
8241  {
8242  CrashImage->Visible = false;
8243  DerailImage->Visible = false;
8244  SPADImage->Visible = false;
8245  TrainFailedImage->Visible = false;
8246  CallOnImage->Visible = false;
8247  SignalStopImage->Visible = false;
8248  BufferAttentionImage->Visible = false;
8249  }
8250  } // if(WarningFlashCount == 0)
8251  // set buttons etc as appropriate
8253  // if forced route cancellation flag set redisplay to clear the cancelled route
8255  {
8257  AllRoutes->RebuildRailwayFlag = false;
8258  }
8259  // deal with approach locking
8261  // deal with ContinuationAutoSigList
8263  // FloatingLabel function
8264  if((TrackInfoOnOffMenuItem->Caption == "Hide") || (TrainStatusInfoOnOffMenuItem->Caption == "Hide Status") ||
8265  (TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable"))
8266  {
8267  TrackTrainFloat(0);
8268  }
8269  else
8270  {
8271  FloatingPanel->Visible = false;
8272  }
8273  // PerformanceLog check function
8274 /*
8275  if(IsPerformancePanelObscuringFloatingLabel(0) && (ShowPerformancePanel))
8276  {
8277  PerformancePanel->Visible = false;
8278  }
8279  else
8280  {
8281 */
8283  {
8284  PerformancePanel->Visible = true;
8285  }
8286  else
8287  {
8288  PerformancePanel->Visible = false;
8289  }
8290 
8292  {
8293  OperatorActionPanel->Visible = true;
8294  }
8295  else
8296  {
8297  OperatorActionPanel->Visible = false;
8298  }
8299 
8300 // }
8301 
8302  // check if a moving train is present on a route-under-construction start element & cancel it if so
8303  if(RouteMode == RouteContinuing)
8304  {
8305  bool FoundFlag;
8306  int RouteStartVecPos;
8307  if(AutoSigsFlag)
8309  FoundFlag);
8310  else if(ConsecSignalsRoute)
8311  RouteStartVecPos = Track->GetVectorPositionFromTrackMap(8, (SigRouteStartMarker->GetHPos()) / 16, (SigRouteStartMarker->GetVPos()) / 16,
8312  FoundFlag);
8313  else
8315  FoundFlag);
8316  if(FoundFlag && (RouteStartVecPos > -1))
8317  {
8318  TTrackElement TrackElement = Track->TrackElementAt(485, RouteStartVecPos);
8319  if(TrackElement.TrainIDOnElement > -1)
8320  {
8321  if(!(TrainController->TrainVectorAtIdent(2, TrackElement.TrainIDOnElement).Stopped()))
8322  {
8324  // replot train as above erases the front element of the train
8326  }
8327  }
8328  }
8329  }
8330  Utilities->CallLogPop(81);
8331  }
8332  catch(const Exception &e)
8333  {
8334  ErrorLog(25, e.Message);
8335  }
8336 }
8337 
8338 // ---------------------------------------------------------------------------
8339 
8340 void __fastcall TInterface::CallingOnButtonClick(TObject *Sender)
8341 {
8342  try
8343  {
8344  TrainController->LogEvent("CallingOnButtonClick");
8345  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CallingOnButtonClick");
8346  if(CallingOnButton->Down)
8347  {
8348  // CallingOnButton->Down = true;
8349  InfoPanel->Visible = true;
8350  InfoPanel->Caption = "CALLING ON: Select signal for call on";
8351  }
8352  else
8353  {
8354  // CallingOnButton->Down = false;
8356  }
8357  AutoRouteStartMarker->PlotOriginal(29, Display); // if overlay not plotted will ignore
8358  SigRouteStartMarker->PlotOriginal(30, Display); // if overlay not plotted will ignore
8359  NonSigRouteStartMarker->PlotOriginal(31, Display); // if overlay not plotted will ignore
8360  CallingOnButton->Enabled = false;
8361 // added at v1.3.0 to ensure doesn't retain focus - will be re-enabled during ClockTimer2 (in SetSaveMenuAndButtons) if required
8362  Utilities->CallLogPop(82);
8363  }
8364  catch(const Exception &e)
8365  {
8366  ErrorLog(26, e.Message);
8367  }
8368 }
8369 
8370 // ---------------------------------------------------------------------------
8371 void __fastcall TInterface::ScreenLeftButtonClick(TObject *Sender)
8372 {
8373  try
8374  {
8375  // have to allow in zoomout mode
8376  TrainController->LogEvent("ScreenLeftButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8377  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenLeftButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8378  Screen->Cursor = TCursor(-11); // Hourglass;
8379  ScreenLeftButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8380  if(!Display->ZoomOutFlag)
8381  {
8382  if(CtrlKey)
8383  {
8384  Display->DisplayOffsetH -= 2;
8385  }
8386  else if(ShiftKey)
8387  {
8389  }
8390  else
8391  {
8393  }
8396  {
8398  }
8399  }
8400  else
8401  {
8402  if(CtrlKey)
8403  {
8405  }
8406  else if(ShiftKey)
8407  {
8409  }
8410  else
8411  {
8413  }
8414  Display->ClearDisplay(0);
8417  Track->PlotSmallRedGap(0);
8418  }
8419  ScreenLeftButton->Enabled = true;
8420  Screen->Cursor = TCursor(-2); // Arrow
8421  Utilities->CallLogPop(83);
8422  }
8423  catch(const Exception &e)
8424  {
8425  ErrorLog(27, e.Message);
8426  }
8427 }
8428 // ---------------------------------------------------------------------------
8429 
8430 void __fastcall TInterface::ScreenRightButtonClick(TObject *Sender)
8431 {
8432  try
8433  {
8434  // have to allow in zoomout mode
8435  TrainController->LogEvent("ScreenRightButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8436  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenRightButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8437  Screen->Cursor = TCursor(-11); // Hourglass;
8438  ScreenRightButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8439  if(!Display->ZoomOutFlag)
8440  {
8441  if(CtrlKey)
8442  {
8443  Display->DisplayOffsetH += 2;
8444  }
8445  else if(ShiftKey)
8446  {
8448  }
8449  else
8450  {
8452  }
8455  {
8457  }
8458  }
8459  else
8460  {
8461  if(CtrlKey)
8462  {
8464  }
8465  else if(ShiftKey)
8466  {
8468  }
8469  else
8470  {
8472  }
8473  Display->ClearDisplay(1);
8476  Track->PlotSmallRedGap(1);
8477  }
8478  ScreenRightButton->Enabled = true;
8479  Screen->Cursor = TCursor(-2); // Arrow
8480  Utilities->CallLogPop(84);
8481  }
8482  catch(const Exception &e)
8483  {
8484  ErrorLog(28, e.Message);
8485  }
8486 }
8487 // ---------------------------------------------------------------------------
8488 
8489 void __fastcall TInterface::ScreenDownButtonClick(TObject *Sender)
8490 {
8491  try
8492  {
8493  // have to allow in zoomout mode
8494  TrainController->LogEvent("ScreenDownButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8495  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenDownButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8496  Screen->Cursor = TCursor(-11); // Hourglass;
8497  ScreenDownButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8498  // BUT - it does prevent it from retaining focus - so can use the cursor keys to scroll the display without being captured by the buttons
8499  if(!Display->ZoomOutFlag)
8500  {
8501  if(CtrlKey)
8502  {
8503  Display->DisplayOffsetV += 2;
8504  }
8505  else if(ShiftKey)
8506  {
8508  }
8509  else
8510  {
8512  }
8515  {
8517  }
8518  }
8519  else
8520  {
8521  if(CtrlKey)
8522  {
8524  }
8525  else if(ShiftKey)
8526  {
8528  }
8529  else
8530  {
8532  }
8533  Display->ClearDisplay(2);
8536  Track->PlotSmallRedGap(2);
8537  }
8538  ScreenDownButton->Enabled = true;
8539  Screen->Cursor = TCursor(-2); // Arrow
8540  Utilities->CallLogPop(85);
8541  }
8542  catch(const Exception &e)
8543  {
8544  ErrorLog(29, e.Message);
8545  }
8546 }
8547 // ---------------------------------------------------------------------------
8548 
8549 void __fastcall TInterface::ScreenUpButtonClick(TObject *Sender)
8550 {
8551  try
8552  {
8553  // have to allow in zoomout mode
8554  TrainController->LogEvent("ScreenUpButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8555  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenUpButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8556  Screen->Cursor = TCursor(-11); // Hourglass;
8557  ScreenUpButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8558  if(!Display->ZoomOutFlag)
8559  {
8560  if(CtrlKey)
8561  {
8562  Display->DisplayOffsetV -= 2;
8563  }
8564  else if(ShiftKey)
8565  {
8567  }
8568  else
8569  {
8571  }
8574  {
8576  }
8577  }
8578  else
8579  {
8580  if(CtrlKey)
8581  {
8583  }
8584  else if(ShiftKey)
8585  {
8587  }
8588  else
8589  {
8591  }
8592  Display->ClearDisplay(3);
8595  Track->PlotSmallRedGap(3);
8596  }
8597  ScreenUpButton->Enabled = true;
8598  Screen->Cursor = TCursor(-2); // Arrow
8599  Utilities->CallLogPop(86);
8600  }
8601  catch(const Exception &e)
8602  {
8603  ErrorLog(30, e.Message);
8604  }
8605 }
8606 // ---------------------------------------------------------------------------
8607 
8608 void __fastcall TInterface::ZoomButtonClick(TObject *Sender)
8609 {
8610  try
8611  {
8612  // have to allow in zoomout mode
8613  TrainController->LogEvent("ZoomButtonClick");
8614  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ZoomButtonClick");
8615  Screen->Cursor = TCursor(-11); // Hourglass;
8616  ZoomButton->Enabled = false; // this takes focus away so the arrow keys can move the display (v2.0.0)
8617  if(Display->ZoomOutFlag) // i.e resume zoomed in view
8618  {
8619  TrainController->LogEvent("ZoomButtonClick + ZoomOutFlag");
8620 // TLevel2OperMode TempLevel2OperMode = Level2OperMode;
8621  if(Level1Mode == BaseMode)
8622  {
8623  InfoPanel->Visible = false; // reset infopanel in case not set later
8624  InfoPanel->Caption = "";
8625  SetLevel1Mode(18);
8626  }
8627  else if(Level1Mode == TrackMode)
8628  {
8629  InfoPanel->Visible = false; // reset infopanel in case not set later
8630  InfoPanel->Caption = "";
8631  // set edit menu items
8633  SetLevel2TrackMode(33); // revert to earlier track mode from zoom
8634  }
8635  else if(Level1Mode == PrefDirMode)
8636  {
8638  SetLevel1Mode(19); // to redisplay infopanel caption "...select start..."
8639  else
8640  SetLevel2PrefDirMode(4); // revert to PrefDirContinuing PrefDir mode
8641  }
8642 // else if(Level1Mode == TrackMode) SetLevel1Mode();//just revert to basic track mode from zoom
8643 // else if(Level1Mode == PrefDirMode) SetLevel1Mode();//just revert to basic PrefDir mode from zoom
8644  else if(Level1Mode == TimetableMode)
8645  {
8646  InfoPanel->Visible = false;
8647  }
8648  // Don't include OperMode or RestartSessionOperMode as they reset the performance file
8649  else if(Level2OperMode == Operating) // similar to SetLevel2OperMode but without resetting BaseTime
8650  {
8651  OperateButton->Enabled = true;
8652  OperateButton->Glyph->LoadFromResourceName(0, "PauseGraphic");
8653  ExitOperationButton->Enabled = true;
8655  }
8656  else if(Level2OperMode == Paused) // similar to SetLevel2OperMode but without resetting RestartTime
8657  {
8658  OperateButton->Enabled = true;
8659  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
8660  ExitOperationButton->Enabled = true;
8661  TTClockAdjButton->Enabled = true;
8664  }
8665  else if(Level2OperMode == PreStart)
8666  {
8667  OperateButton->Enabled = true;
8668  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
8669  ExitOperationButton->Enabled = true;
8670  TTClockAdjButton->Enabled = true;
8672  }
8673  Display->ZoomOutFlag = false; // reset this after level modes called so gap flash stays set if set to begin with
8675  ClearandRebuildRailway(43); // need to call this after ZoomOutFlag reset to display track, even if Clearand... already called
8676  // earlier during level mode setting - because until ZoomOutFlag reset PlotOutput plots nothing
8677  }
8678  else // set zoomed out view
8679  {
8680  TrainController->LogEvent("ZoomButtonClick + != ZoomOutFlag");
8681  Display->ZoomOutFlag = true;
8683  FileMenu->Enabled = false;
8684  ModeMenu->Enabled = false;
8685  EditMenu->Enabled = false;
8686  TextBox->Visible = false;
8687  LocationNameTextBox->Visible = false;
8688  TTClockAdjButton->Enabled = false;
8689 // DisablePanelsStoreMainMenuStates();//ensure Display->ZoomOutFlag set true before calling
8690  // start assuming normal view is at centre of ZoomOut & calc excesses at each side
8691  int OVOffH_NVCentre = Display->DisplayOffsetH - (1.5 * Utilities->ScreenElementWidth);
8692 // start zoomout centre at DisplayOffsetH + 30 - zoomout width/2 = -(1.5 * 60)
8693  int LeftExcess = OVOffH_NVCentre - Track->GetHLocMin();
8694  int RightExcess = Track->GetHLocMax() - OVOffH_NVCentre - ((4 * Utilities->ScreenElementWidth) - 1);
8695  if((LeftExcess > 0) && (RightExcess > 0))
8696  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre;
8697  else if((LeftExcess > 0) && (RightExcess <= 0))
8698  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre + ((RightExcess) / (Utilities->ScreenElementWidth / 2)) *
8699  (Utilities->ScreenElementWidth / 2); // normalise to nearest screen
8700  else if((LeftExcess <= 0) && (RightExcess > 0))
8701  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre - ((LeftExcess) / (Utilities->ScreenElementWidth / 2)) * (Utilities->ScreenElementWidth / 2);
8702  else
8703  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre; // no excess at either side, so display in centre
8704 
8705  int OVOffV_NVCentre = Display->DisplayOffsetV - (1.5 * Utilities->ScreenElementHeight);
8706  int TopExcess = OVOffV_NVCentre - Track->GetVLocMin();
8707  int BotExcess = Track->GetVLocMax() - OVOffV_NVCentre - ((4 * Utilities->ScreenElementHeight) - 1);
8708  if((TopExcess > 0) && (BotExcess > 0))
8709  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre;
8710  else if((TopExcess > 0) && (BotExcess <= 0))
8711  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre + ((BotExcess) / (Utilities->ScreenElementHeight / 2)) *
8712  (Utilities->ScreenElementHeight / 2); // normalise to nearest half screen
8713  else if((TopExcess <= 0) && (BotExcess > 0))
8714  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre - ((TopExcess) / (Utilities->ScreenElementHeight / 2)) * (Utilities->ScreenElementHeight / 2);
8715  else
8716  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre; // no excess at either side, so display in centre
8717 
8718  Display->ClearDisplay(4);
8722  Track->PlotSmallRedGap(4);
8723  ZoomButton->Glyph->LoadFromResourceName(0, "ZoomIn");
8724  }
8725  Screen->Cursor = TCursor(-2); // Arrow
8726  ZoomButton->Enabled = true; // restore, see above
8727  Utilities->CallLogPop(87);
8728  }
8729  catch(const Exception &e)
8730  {
8731  ErrorLog(31, e.Message);
8732  }
8733 }
8734 // ---------------------------------------------------------------------------
8735 
8736 void __fastcall TInterface::HomeButtonClick(TObject *Sender)
8737 {
8738  try
8739  {
8740  // have to allow in zoomout mode
8741  TrainController->LogEvent("HomeButtonClick");
8742  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",HomeButtonClick");
8743  Screen->Cursor = TCursor(-11); // Hourglass;
8744  HomeButton->Enabled = false; // this takes focus away so the arrow keys can move the display (v2.0.0)
8745  if(!Display->ZoomOutFlag) // zoomed in mode
8746  {
8747  TrainController->LogEvent("HomeButtonClick + zoomed in mode");
8751  {
8753  }
8754  }
8755  else
8756  {
8757  // zoomed out mode
8758  // start assuming normal view is at centre of ZoomOut & calc excesses at each side
8759  TrainController->LogEvent("HomeButtonClick + zoomed out mode");
8761  Display->ClearDisplay(9);
8764  Track->PlotSmallRedGap(5);
8765  }
8766  Screen->Cursor = TCursor(-2); // Arrow
8767  HomeButton->Enabled = true; // restore, see above
8768  Utilities->CallLogPop(88);
8769  }
8770  catch(const Exception &e)
8771  {
8772  ErrorLog(32, e.Message);
8773  }
8774 }
8775 
8776 // ---------------------------------------------------------------------------
8777 void __fastcall TInterface::NewHomeButtonClick(TObject *Sender)
8778 {
8779  try
8780  {
8781  TrainController->LogEvent("NewHomeButtonClick");
8782  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NewHomeButtonClick");
8783  NewHomeButton->Enabled = false; // this takes focus away so the arrow keys can move the display (v2.0.0)
8784  if(!Display->ZoomOutFlag) // zoomed in mode
8785  {
8788  ResetChangedFileDataAndCaption(23, false); // false because no major changes made
8789  }
8790  else
8791  {
8794  }
8795  Utilities->CallLogPop(1188);
8796  NewHomeButton->Enabled = true; // restore, see above
8797  }
8798  catch(const Exception &e)
8799  {
8800  ErrorLog(174, e.Message);
8801  }
8802 }
8803 
8804 // ---------------------------------------------------------------------------
8805 void __fastcall TInterface::EditMenuClick(TObject *Sender)
8806  // added at v2.1.0 to allow CTRL+X, CTRL+C & CTRL+V in edit menu (see case BaseMode for more information)
8807 {
8808  try
8809  {
8810  CopyMenuItem->ShortCut = TextToShortCut("Ctrl+C");
8811  CutMenuItem->ShortCut = TextToShortCut("Ctrl+X");
8812  PasteMenuItem->ShortCut = TextToShortCut("Ctrl+V");
8813  }
8814  catch(const Exception &e)
8815  {
8816  ErrorLog(196, e.Message);
8817  }
8818 }
8819 
8820 // ---------------------------------------------------------------------------
8821 void __fastcall TInterface::SelectMenuItemClick(TObject *Sender)
8822 {
8823 // draw a rectangle with the left mouse button, enclosing whole 16 x 16 squares
8824  try
8825  {
8826  TrainController->LogEvent("SelectMenuItemClick");
8827  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectMenuItemClick");
8828  if(Level1Mode == TrackMode)
8829  {
8830  SelectionValid = false;
8832  SetLevel2TrackMode(34);
8834  {
8835  ShowMessage("Please be aware when pasting that anything inside the pasted area will be overwritten.\n\nThis warning will not be shown again.");
8836  PasteWarningSentFlag = true;
8837  }
8838  }
8839  else if(Level1Mode == PrefDirMode)
8840  {
8843  }
8844  Utilities->CallLogPop(1189);
8845  }
8846  catch(const Exception &e)
8847  {
8848  ErrorLog(145, e.Message);
8849  }
8850 }
8851 
8852 // ---------------------------------------------------------------------------
8853 void __fastcall TInterface::ReselectMenuItemClick(TObject *Sender)
8854 {
8855  try
8856  {
8857  TrainController->LogEvent("ReselectMenuItemClick");
8858  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ReselectMenuItemClick");
8859  if((SelectBitmap->Height == 0) || (SelectBitmap->Width == 0))
8860  {
8861  Utilities->CallLogPop(1424);
8862  return;
8863  }
8864 
8865  int TLHCH = SelectBitmapHLoc;
8866  int TLHCV = SelectBitmapVLoc;
8867  int BRHCH = TLHCH + (SelectBitmap->Width / 16);
8868  int BRHCV = TLHCV + (SelectBitmap->Height / 16);
8869  TRect NewSelectRect(TLHCH, TLHCV, BRHCH, BRHCV);
8870  SelectRect = NewSelectRect;
8872  // set bitmap to reselected area (may be different if flip or mirror had been selected earlier)
8873  TRect Dest(0, 0, SelectBitmap->Width, SelectBitmap->Height);
8874  TRect Source(((SelectRect.left - Display->DisplayOffsetH) * 16), ((SelectRect.top - Display->DisplayOffsetV) * 16),
8875  ((SelectRect.right - Display->DisplayOffsetH) * 16), ((SelectRect.bottom - Display->DisplayOffsetV) * 16));
8876  SelectBitmap->Canvas->CopyRect(Dest, MainScreen->Canvas, Source);
8877 
8878  SelectionValid = true;
8879  ReselectMenuItem->Enabled = false;
8880  CutMenuItem->Enabled = true;
8881  CopyMenuItem->Enabled = true;
8882  FlipMenuItem->Enabled = true;
8883  MirrorMenuItem->Enabled = true;
8884  RotRightMenuItem->Enabled = true;
8885  RotLeftMenuItem->Enabled = true;
8886  RotateMenuItem->Enabled = true;
8887  PasteMenuItem->Enabled = false;
8888  DeleteMenuItem->Enabled = true;
8889  if(Track->IsTrackFinished())
8890  SelectLengthsMenuItem->Enabled = true; // only permit if finished because reverts to DistanceStart
8891  else
8892  SelectLengthsMenuItem->Enabled = false; // and that can only be used if track linked
8893  SelectBiDirPrefDirsMenuItem->Visible = false;
8894  CancelSelectionMenuItem->Enabled = true;
8895  mbLeftDown = false;
8896  // Level1Mode = TrackMode;
8897  // SetLevel1Mode(68);
8899  SetLevel2TrackMode(47);
8900  Utilities->CallLogPop(1425);
8901  }
8902  catch(const Exception &e)
8903  {
8904  ErrorLog(146, e.Message);
8905  }
8906 }
8907 
8908 // ---------------------------------------------------------------------------
8909 void __fastcall TInterface::CutMenuItemClick(TObject *Sender)
8910 {
8911  try
8912  {
8913  TrainController->LogEvent("CutMenuItemClick");
8914  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CutMenuItemClick");
8915  // Level1Mode = TrackMode;
8916  // SetLevel1Mode(69);
8918  SetLevel2TrackMode(35);
8919  Utilities->CallLogPop(1190);
8920  }
8921  catch(const Exception &e)
8922  {
8923  ErrorLog(147, e.Message);
8924  }
8925 }
8926 // ---------------------------------------------------------------------------
8927 
8928 void __fastcall TInterface::CopyMenuItemClick(TObject *Sender)
8929 {
8930  try
8931  {
8932  TrainController->LogEvent("CopyMenuItemClick");
8933  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CopyMenuItemClick");
8934  // Level1Mode = TrackMode;
8935  // SetLevel1Mode(70);
8937  SetLevel2TrackMode(36);
8938  Utilities->CallLogPop(1191);
8939  }
8940  catch(const Exception &e)
8941  {
8942  ErrorLog(148, e.Message);
8943  }
8944 }
8945 
8946 // ---------------------------------------------------------------------------
8947 void __fastcall TInterface::FlipMenuItemClick(TObject *Sender)
8948 {
8949  try
8950  {
8951  TrainController->LogEvent("FlipMenuItemClick");
8952  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",FlipMenuItemClick");
8953  // reset values in SelectVector
8954  int VerSum = SelectRect.top + SelectRect.bottom - 1;
8955  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
8956  {
8957  // Note: (changed again in v2.4.0 to keep attributes) need to change flip, mirror & 180deg functions as only change speedtag without changing anything else.
8958  // This didn't matter before new paste with attributes added at v2.2.0 as a new element was built from the speedtag,
8959  // but now if do a reselect then cut and paste with attributes the wrong graphic is pasted and all other attributes
8960  // are wrong. Need to rebuild a new TrackElement from the new speedtag and use that in the select vector.
8961  // Note that if use Flip, mirror etc then all attributes lost anyway so ok to build a basic element.
8962  int VLoc = VerSum - Track->SelectVectorAt(8, x).VLoc;
8963  int HLoc = Track->SelectVectorAt(7, x).HLoc;
8965  TE.VLoc = VLoc;
8966  TE.HLoc = HLoc;
8967 
8968  TE.ActiveTrackElementName = Track->SelectVectorAt(37, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
8970  TE.Length01 = Track->SelectVectorAt(39, x).Length01;
8971  TE.Length23 = Track->SelectVectorAt(40, x).Length23;
8974  TE.SigAspect = Track->SelectVectorAt(43, x).SigAspect;
8975  Track->SelectVectorAt(26, x) = TE;
8976  }
8977  // reset values in SelectTextVector
8978  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(0); x++)
8979  {
8981  // also subtract font height, brings position approximately right
8982  TextItem->VPos = ((VerSum * 16) + 15) - TextItem->VPos - abs(TextItem->Font->Height);
8983  }
8984  // reset values in SelectGraphicVector so the midpoint of the graphic flips about the midline of the selection
8985  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
8986  {
8987  int MidVPosBeforeFlip = Track->SelectGraphicVector.at(x).VPos + (Track->SelectGraphicVector.at(x).Height) / 2;
8988  int MidVPosAfterFlip = ((VerSum * 16) + 15) - MidVPosBeforeFlip;
8989  int TopPosAfterFlip = MidVPosAfterFlip - (Track->SelectGraphicVector.at(x).Height) / 2;
8990  Track->SelectGraphicVector.at(x).VPos = TopPosAfterFlip;
8991  }
8993  SetLevel2TrackMode(48);
8994  Utilities->CallLogPop(1426);
8995  }
8996  catch(const Exception &e)
8997  {
8998  ErrorLog(149, e.Message);
8999  }
9000 }
9001 
9002 // ---------------------------------------------------------------------------
9003 void __fastcall TInterface::MirrorMenuItemClick(TObject *Sender)
9004 {
9005  try
9006  {
9007  TrainController->LogEvent("MirrorMenuItemClick");
9008  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MirrorMenuItemClick");
9009  // reset values in SelectVector
9010  int HorSum = SelectRect.left + SelectRect.right - 1;
9011  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9012  {
9013  // See note above for FlipMenuItem relating to mods for v2.2.0
9014  int VLoc = Track->SelectVectorAt(22, x).VLoc;
9015  int HLoc = HorSum - Track->SelectVectorAt(6, x).HLoc;
9017  TE.VLoc = VLoc;
9018  TE.HLoc = HLoc;
9019 
9020  TE.ActiveTrackElementName = Track->SelectVectorAt(44, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9022  TE.Length01 = Track->SelectVectorAt(46, x).Length01;
9023  TE.Length23 = Track->SelectVectorAt(47, x).Length23;
9026  TE.SigAspect = Track->SelectVectorAt(50, x).SigAspect;
9027 
9028 // if(Track->SelectVectorAt(28, x).TrackType == SignalPost) TE.SigAspect = Track->SelectVectorAt(29, x).SigAspect;//TrackType will be the same
9029  Track->SelectVectorAt(30, x) = TE;
9030 // Track->SelectVectorAt(, x).HLoc = HorSum - Track->SelectVectorAt(, x).HLoc;
9031 // Track->SelectVectorAt(, x).SpeedTag = Track->MirrorArray[Track->SelectVectorAt(, x).SpeedTag];
9032  }
9033  // reset values in SelectTextVector
9034  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(1); x++)
9035  {
9037  // also subtract half font height for each letter of text, brings position approximately right
9038  TextItem->HPos = ((HorSum * 16) + 15) - TextItem->HPos - (TextItem->TextString.Length() * 0.5 * abs(TextItem->Font->Height));
9039  }
9040  // reset values in SelectGraphicVector so the midpoint of the graphic mirrors about the midline of the selection
9041  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9042  {
9043  int MidHPosBeforeMirror = Track->SelectGraphicVector.at(x).HPos + (Track->SelectGraphicVector.at(x).Width) / 2;
9044  int MidHPosAfterMirror = ((HorSum * 16) + 15) - MidHPosBeforeMirror;
9045  int LeftPosAfterMirror = MidHPosAfterMirror - (Track->SelectGraphicVector.at(x).Width) / 2;
9046  if(LeftPosAfterMirror < (SelectRect.left * 16)) // shouldn't go below left but check
9047  {
9048  LeftPosAfterMirror = SelectRect.left * 16;
9049  }
9050  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterMirror;
9051  }
9053  SetLevel2TrackMode(49);
9054  Utilities->CallLogPop(1427);
9055  }
9056  catch(const Exception &e)
9057  {
9058  ErrorLog(150, e.Message);
9059  }
9060 }
9061 
9062 // ---------------------------------------------------------------------------
9063 void __fastcall TInterface::RotateMenuItemClick(TObject *Sender)
9064 {
9065  try
9066  {
9067  TrainController->LogEvent("Rotate180MenuItemClick");
9068  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",Rotate180MenuItemClick");
9069  // reset values in SelectVector
9070  int HorSum = SelectRect.left + SelectRect.right - 1;
9071  int VerSum = SelectRect.top + SelectRect.bottom - 1;
9072  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9073  {
9074  // See note above for FlipMenuItem relating to mods for v2.2.0
9075  int VLoc = VerSum - Track->SelectVectorAt(23, x).VLoc;
9076  int HLoc = HorSum - Track->SelectVectorAt(36, x).HLoc;
9078  TE.VLoc = VLoc;
9079  TE.HLoc = HLoc;
9080 
9081  TE.ActiveTrackElementName = Track->SelectVectorAt(51, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9083  TE.Length01 = Track->SelectVectorAt(53, x).Length01;
9084  TE.Length23 = Track->SelectVectorAt(54, x).Length23;
9087  TE.SigAspect = Track->SelectVectorAt(57, x).SigAspect;
9088 
9089 // if(Track->SelectVectorAt(32, x).TrackType == SignalPost) TE.SigAspect = Track->SelectVectorAt(33, x).SigAspect; dropped in v2.4.0 for above
9090  Track->SelectVectorAt(34, x) = TE;
9091 // TTrackElement &TempEl = Track->SelectVectorAt(13, x);
9092 // TempEl.HLoc = HorSum - TempEl.HLoc;
9093 // TempEl.VLoc = VerSum - TempEl.VLoc;
9094 // TempEl.SpeedTag = Track->MirrorArray[Track->FlipArray[TempEl.SpeedTag]];
9095  }
9096  // reset values in SelectTextVector
9097  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(2); x++)
9098  {
9100  // also subtract half font height for each letter of text, brings position approximately right horizontally
9101  TextItem->HPos = ((HorSum * 16) + 15) - TextItem->HPos - (TextItem->TextString.Length() * 0.5 * abs(TextItem->Font->Height));
9102  // also subtract font height, brings position approximately right vertically
9103  TextItem->VPos = ((VerSum * 16) + 15) - TextItem->VPos - abs(TextItem->Font->Height);
9104  }
9105  // reset flip values in SelectGraphicVector so the midpoint of the graphic flips about the midline of the selection
9106  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9107  {
9108  int MidVPosBeforeFlip = Track->SelectGraphicVector.at(x).VPos + (Track->SelectGraphicVector.at(x).Height) / 2;
9109  int MidVPosAfterFlip = ((VerSum * 16) + 15) - MidVPosBeforeFlip;
9110  int TopPosAfterFlip = MidVPosAfterFlip - (Track->SelectGraphicVector.at(x).Height) / 2;
9111  if(TopPosAfterFlip < (SelectRect.top * 16)) // shouldn't go above top but check
9112  {
9113  TopPosAfterFlip = SelectRect.top * 16;
9114  }
9115  Track->SelectGraphicVector.at(x).VPos = TopPosAfterFlip;
9116  }
9117  // reset mirror in SelectGraphicVector so the midpoint of the graphic mirrors about the midline of the selection
9118  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9119  {
9120  int MidHPosBeforeMirror = Track->SelectGraphicVector.at(x).HPos + (Track->SelectGraphicVector.at(x).Width) / 2;
9121  int MidHPosAfterMirror = ((HorSum * 16) + 15) - MidHPosBeforeMirror;
9122  int LeftPosAfterMirror = MidHPosAfterMirror - (Track->SelectGraphicVector.at(x).Width) / 2;
9123  if(LeftPosAfterMirror < (SelectRect.left * 16)) // shouldn't go below left but check
9124  {
9125  LeftPosAfterMirror = SelectRect.left * 16;
9126  }
9127  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterMirror;
9128  }
9129  // Level1Mode = TrackMode;
9130  // SetLevel1Mode(73);
9132  SetLevel2TrackMode(50);
9133  Utilities->CallLogPop(1435);
9134  }
9135  catch(const Exception &e)
9136  {
9137  ErrorLog(151, e.Message);
9138  }
9139 }
9140 // ---------------------------------------------------------------------------
9141 
9142 void __fastcall TInterface::RotRightMenuItemClick(TObject *Sender)
9143 {
9144  try
9145  {
9146  TrainController->LogEvent("RotateRight90MenuItemClick");
9147  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RotateRight90MenuItemClick");
9148  Screen->Cursor = TCursor(-11); // Hourglass
9149  // check first if a square and if not give message & quit
9150  if((SelectRect.right - SelectRect.left) != (SelectRect.bottom - SelectRect.top))
9151  {
9152  // use left vertical side to make square & keep top lh corner unless rhs would exceed display, in which case use the right vertical & keep to rh corner
9153  int VertSize = SelectRect.bottom - SelectRect.top;
9154  if((SelectRect.Left + VertSize - Display->DisplayOffsetH) > Utilities->ScreenElementWidth)
9155  {
9156  // use right hand vertical & make square to left of that
9157  SelectRect.left = SelectRect.right - VertSize;
9158  }
9159  else
9160  {
9161  SelectRect.right = SelectRect.left + VertSize;
9162  }
9165  int button = Application->MessageBox
9166  (L"Original selection adjusted to make it square. 'OK' to keep this selection or 'Cancel' to make a new selection",
9167  L"Left click and hold here to move this message box", MB_OKCANCEL);
9168  if(button == IDCANCEL)
9169  {
9170  ResetSelectRect();
9171  Level1Mode = TrackMode; // call this first to clear everything, then set PrefDir mode
9172  SetLevel1Mode(133);
9174  SetLevel2TrackMode(59);
9176  Screen->Cursor = TCursor(-2); // Arrow
9177  Utilities->CallLogPop(2121);
9178  return;
9179  }
9180  }
9181  // set SelectBitmap (only need the dimensions here as not moving the selection)
9184  SelectBitmap->Width = (SelectRect.right - SelectRect.left) * 16;
9185  SelectBitmap->Height = (SelectRect.bottom - SelectRect.top) * 16;
9186  // store track elements and text in select vectors
9188  TTrackElement TempElement; // default element
9189  bool FoundFlag;
9190  for(int x = SelectRect.left; x < SelectRect.right; x++)
9191  {
9192  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9193  {
9194  int ATVecPos = Track->GetVectorPositionFromTrackMap(57, x, y, FoundFlag);
9195  if(FoundFlag)
9196  {
9197  TempElement = Track->TrackElementAt(959, ATVecPos);
9198  if(TempElement.SpeedTag > 0)
9199  Track->SelectPush(TempElement);
9200  }
9201  }
9202  }
9203  // now store inactive elements
9204  for(int x = SelectRect.left; x < SelectRect.right; x++)
9205  {
9206  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9207  {
9208  TTrack::TIMPair IATVecPair = Track->GetVectorPositionsFromInactiveTrackMap(28, x, y, FoundFlag);
9209  if(FoundFlag)
9210  {
9211  TempElement = Track->InactiveTrackElementAt(126, IATVecPair.first);
9212  Track->SelectPush(TempElement); // only want SpeedTag & location set, rest defaults
9213  if(IATVecPair.second != IATVecPair.first) // 2 elements stored at location, i.e. platforms
9214  {
9215  TempElement = Track->InactiveTrackElementAt(127, IATVecPair.second);
9216  Track->SelectPush(TempElement);
9217  }
9218  }
9219  }
9220  }
9221  // store text items
9222  int LowSelectHPos = SelectRect.left * 16;
9223  int HighSelectHPos = SelectRect.right * 16;
9224  int LowSelectVPos = SelectRect.top * 16;
9225  int HighSelectVPos = SelectRect.bottom * 16;
9226  TextHandler->SelectTextVector.clear();
9227  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
9228  {
9229  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr < TextHandler->TextVector.end(); TextPtr++)
9230  {
9231  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos < HighSelectVPos))
9232  {
9233  // have to create a new TextItem in order to create a new Font object
9234  // BUT: only create new items where they don't appear as named location names
9235  // in SelectVector, since those names shouldn't be copied or pasted.
9236  // NB: altered for PasteWithAttributes - at v2.2.0 save the named element but prefix it with "##**"
9237  // so can paste or not depending on which type of paste is being used (unlikely to use that in a real name)
9238  bool SelectVectorNamedElement = false;
9239  AnsiString SelectTextString; // new at v2.2.0
9240  for(unsigned int x = 0; x < Track->SelectVector.size(); x++)
9241  {
9242  if(Track->SelectVector.at(x).LocationName == TextPtr->TextString)
9243  {
9244  SelectVectorNamedElement = true;
9245  break;
9246  }
9247  }
9248  if(SelectVectorNamedElement) // changed at v2.2.0
9249  {
9250  SelectTextString = "##**" + TextPtr->TextString; // new at v2.2.0
9251  }
9252  else // new at v2.2.0
9253  {
9254  SelectTextString = TextPtr->TextString;
9255  }
9256  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
9257  TextHandler->SelectTextVector.push_back(TextItem); // changed at v2.2.0
9258  }
9259  }
9260  }
9261  // store graphic items, but first clear SelectGraphicVector
9262  Track->SelectGraphicVector.clear();
9263  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
9264  {
9265  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = Track->UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
9266  UserGraphicPtr++)
9267  {
9268  if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) && (UserGraphicPtr->VPos >=
9269  LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
9270  {
9271  Track->SelectGraphicVector.push_back(*UserGraphicPtr);
9272  }
9273  }
9274  }
9275  // now transform the H & V for rh rotate
9276  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9277  {
9278  int HLoc = SelectRect.bottom - 1 + SelectRect.left - Track->SelectVectorAt(74, x).VLoc;
9279  int VLoc = SelectRect.top - SelectRect.left + Track->SelectVectorAt(75, x).HLoc;
9281  TE.VLoc = VLoc;
9282  TE.HLoc = HLoc;
9283 
9284  TE.ActiveTrackElementName = Track->SelectVectorAt(58, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9286  TE.Length01 = Track->SelectVectorAt(60, x).Length01;
9287  TE.Length23 = Track->SelectVectorAt(61, x).Length23;
9290  TE.SigAspect = Track->SelectVectorAt(64, x).SigAspect;
9291  Track->SelectVectorAt(65, x) = TE;
9292  }
9293  // reset values in SelectTextVector
9294  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(3); x++)
9295  {
9296 // no point trying to locate text properly as it stays horizontal so will always be wrongly placed, just list all itels vertically at lhs
9297 // & if a lot then some will extend beyond the selection
9299  // also subtract half font height for each letter of text, brings position approximately right horizontally
9300  TextItem->HPos = (SelectRect.left) * 16;
9301  TextItem->VPos = (SelectRect.top + x) * 16;
9302  }
9303  // reset values in SelectGraphicVector
9304  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9305  {
9306  int MidHPosBeforeRotate = Track->SelectGraphicVector.at(x).HPos + Track->SelectGraphicVector.at(x).Width / 2;
9307  int MidVPosBeforeRotate = Track->SelectGraphicVector.at(x).VPos + Track->SelectGraphicVector.at(x).Height / 2;
9308  int MidHPosAfterRotate = ((SelectRect.bottom * 16) - 1) + (SelectRect.left * 16) - MidVPosBeforeRotate;
9309  int MidVPosAfterRotate = ((SelectRect.top - SelectRect.left) * 16) + MidHPosBeforeRotate;
9310  int LeftPosAfterRotate = MidHPosAfterRotate - (Track->SelectGraphicVector.at(x).Width) / 2;
9311  int TopPosAfterRotate = MidVPosAfterRotate - (Track->SelectGraphicVector.at(x).Height) / 2;
9312  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterRotate;
9313  Track->SelectGraphicVector.at(x).VPos = TopPosAfterRotate;
9314  }
9315  Screen->Cursor = TCursor(-2); // Arrow
9317  SetLevel2TrackMode(60);
9318  Utilities->CallLogPop(2122);
9319  }
9320  catch(const Exception &e)
9321  {
9322  ErrorLog(205, e.Message);
9323  }
9324 }
9325 
9326 // ---------------------------------------------------------------------------
9327 
9328 void __fastcall TInterface::RotLeftMenuItemClick(TObject *Sender)
9329 {
9330  try
9331  {
9332  TrainController->LogEvent("RotateLeft90MenuItemClick");
9333  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RotateLeft90MenuItemClick");
9334  Screen->Cursor = TCursor(-11); // Hourglass;
9335  // check first if a square and if not give message & quit
9336  if((SelectRect.right - SelectRect.left) != (SelectRect.bottom - SelectRect.top))
9337  {
9338  // use left vertical side to make square & keep top lh corner unless rhs would exceed display, in which case use the right vertical & keep to rh corner
9339  int VertSize = SelectRect.bottom - SelectRect.top;
9340  if((SelectRect.Left + VertSize - Display->DisplayOffsetH) > Utilities->ScreenElementWidth)
9341  {
9342  // use right hand vertical & make square to left of that
9343  SelectRect.left = SelectRect.right - VertSize;
9344  }
9345  else
9346  {
9347  SelectRect.right = SelectRect.left + VertSize;
9348  }
9351  int button = Application->MessageBox
9352  (L"Original selection adjusted to make it square. 'OK' to keep this selection or 'Cancel' to make a new selection",
9353  L"Left click and hold here to move this message box", MB_OKCANCEL);
9354  if(button == IDCANCEL)
9355  {
9356  ResetSelectRect();
9357  Level1Mode = TrackMode; // call this first to clear everything, then set PrefDir mode
9358  SetLevel1Mode(134);
9360  SetLevel2TrackMode(61);
9362  Screen->Cursor = TCursor(-2); // Arrow
9363  Utilities->CallLogPop(2123);
9364  return;
9365  }
9366  }
9367  // set SelectBitmap (only need the dimensions here as not moving the selection)
9370  SelectBitmap->Width = (SelectRect.right - SelectRect.left) * 16;
9371  SelectBitmap->Height = (SelectRect.bottom - SelectRect.top) * 16;
9372  // store track elements and text in select vectors
9374  TTrackElement TempElement; // default element
9375  bool FoundFlag;
9376  for(int x = SelectRect.left; x < SelectRect.right; x++)
9377  {
9378  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9379  {
9380  int ATVecPos = Track->GetVectorPositionFromTrackMap(58, x, y, FoundFlag);
9381  if(FoundFlag)
9382  {
9383  TempElement = Track->TrackElementAt(960, ATVecPos);
9384  if(TempElement.SpeedTag > 0)
9385  Track->SelectPush(TempElement);
9386  }
9387  }
9388  }
9389  // now store inactive elements
9390  for(int x = SelectRect.left; x < SelectRect.right; x++)
9391  {
9392  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9393  {
9394  TTrack::TIMPair IATVecPair = Track->GetVectorPositionsFromInactiveTrackMap(29, x, y, FoundFlag);
9395  if(FoundFlag)
9396  {
9397  TempElement = Track->InactiveTrackElementAt(128, IATVecPair.first);
9398  Track->SelectPush(TempElement); // only want SpeedTag & location set, rest defaults
9399  if(IATVecPair.second != IATVecPair.first) // 2 elements stored at location, i.e. platforms
9400  {
9401  TempElement = Track->InactiveTrackElementAt(129, IATVecPair.second);
9402  Track->SelectPush(TempElement);
9403  }
9404  }
9405  }
9406  }
9407  // store text items
9408  int LowSelectHPos = SelectRect.left * 16;
9409  int HighSelectHPos = SelectRect.right * 16;
9410  int LowSelectVPos = SelectRect.top * 16;
9411  int HighSelectVPos = SelectRect.bottom * 16;
9412  TextHandler->SelectTextVector.clear();
9413  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
9414  {
9415  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr < TextHandler->TextVector.end(); TextPtr++)
9416  {
9417  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos < HighSelectVPos))
9418  {
9419  // have to create a new TextItem in order to create a new Font object
9420  // BUT: only create new items where they don't appear as named location names
9421  // in SelectVector, since those names shouldn't be copied or pasted.
9422  // NB: altered for PasteWithAttributes - at v2.2.0 save the named element but prefix it with "##**"
9423  // so can paste or not depending on which type of paste is being used (unlikely to use that in a real name)
9424  bool SelectVectorNamedElement = false;
9425  AnsiString SelectTextString; // new at v2.2.0
9426  for(unsigned int x = 0; x < Track->SelectVector.size(); x++)
9427  {
9428  if(Track->SelectVector.at(x).LocationName == TextPtr->TextString)
9429  {
9430  SelectVectorNamedElement = true;
9431  break;
9432  }
9433  }
9434  if(SelectVectorNamedElement) // changed at v2.2.0
9435  {
9436  SelectTextString = "##**" + TextPtr->TextString; // new at v2.2.0
9437  }
9438  else // new at v2.2.0
9439  {
9440  SelectTextString = TextPtr->TextString;
9441  }
9442  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
9443  TextHandler->SelectTextVector.push_back(TextItem); // changed at v2.2.0
9444  }
9445  }
9446  }
9447  // store graphic items, but first clear SelectGraphicVector
9448  Track->SelectGraphicVector.clear();
9449  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
9450  {
9451  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = Track->UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
9452  UserGraphicPtr++)
9453  {
9454  if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) && (UserGraphicPtr->VPos >=
9455  LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
9456  {
9457  Track->SelectGraphicVector.push_back(*UserGraphicPtr);
9458  }
9459  }
9460  }
9461  // now transform the H & V for lh rotate
9462  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9463  {
9464  int HLoc = SelectRect.left - SelectRect.top + Track->SelectVectorAt(76, x).VLoc;
9465  int VLoc = SelectRect.bottom - 1 + SelectRect.left - Track->SelectVectorAt(77, x).HLoc;
9467  TE.VLoc = VLoc;
9468  TE.HLoc = HLoc;
9469 
9470  TE.ActiveTrackElementName = Track->SelectVectorAt(66, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9472  TE.Length01 = Track->SelectVectorAt(68, x).Length01;
9473  TE.Length23 = Track->SelectVectorAt(69, x).Length23;
9476  TE.SigAspect = Track->SelectVectorAt(72, x).SigAspect;
9477  Track->SelectVectorAt(73, x) = TE;
9478  }
9479  // reset values in SelectTextVector
9480  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(4); x++)
9481  {
9482 // no point trying to locate text properly as it stays horizontal so will always be wrongly placed, just list all itels vertically at lhs
9483 // & if a lot then some will extend beyond the selection
9485  // also subtract half font height for each letter of text, brings position approximately right horizontally
9486  TextItem->HPos = (SelectRect.left) * 16;
9487  TextItem->VPos = (SelectRect.top + x) * 16;
9488  }
9489  // reset values in SelectGraphicVector
9490  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9491  {
9492  int MidHPosBeforeRotate = Track->SelectGraphicVector.at(x).HPos + Track->SelectGraphicVector.at(x).Width / 2;
9493  int MidVPosBeforeRotate = Track->SelectGraphicVector.at(x).VPos + Track->SelectGraphicVector.at(x).Height / 2;
9494  int MidHPosAfterRotate = ((SelectRect.left - SelectRect.top) * 16) + MidVPosBeforeRotate;
9495  int MidVPosAfterRotate = ((SelectRect.bottom * 16) - 1) + (SelectRect.left * 16) - MidHPosBeforeRotate;
9496  int LeftPosAfterRotate = MidHPosAfterRotate - (Track->SelectGraphicVector.at(x).Width) / 2;
9497  int TopPosAfterRotate = MidVPosAfterRotate - (Track->SelectGraphicVector.at(x).Height) / 2;
9498  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterRotate;
9499  Track->SelectGraphicVector.at(x).VPos = TopPosAfterRotate;
9500  }
9501  Screen->Cursor = TCursor(-2); // Arrow
9503  SetLevel2TrackMode(62);
9504  Utilities->CallLogPop(2124);
9505  }
9506  catch(const Exception &e)
9507  {
9508  ErrorLog(206, e.Message);
9509  }
9510 }
9511 
9512 // ---------------------------------------------------------------------------
9513 
9514 void __fastcall TInterface::PasteMenuItemClick(TObject *Sender)
9515 {
9516  try
9517  {
9518  TrainController->LogEvent("PasteMenuItemClick");
9519  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PasteMenuItemClick");
9520  // Level1Mode = TrackMode;
9521  // SetLevel1Mode(74);
9523  SetLevel2TrackMode(58);
9524  Utilities->CallLogPop(2060);
9525  }
9526  catch(const Exception &e)
9527  {
9528  ErrorLog(198, e.Message);
9529  }
9530 }
9531 
9532 // ---------------------------------------------------------------------------
9533 void __fastcall TInterface::DeleteMenuItemClick(TObject *Sender)
9534 {
9535  try
9536  {
9537  TrainController->LogEvent("DeleteMenuItemClick");
9538  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteMenuItemClick");
9539  // Level1Mode = TrackMode;
9540  // SetLevel1Mode(75);
9542  SetLevel2TrackMode(38);
9543  Utilities->CallLogPop(1193);
9544  }
9545  catch(const Exception &e)
9546  {
9547  ErrorLog(153, e.Message);
9548  }
9549 }
9550 // ---------------------------------------------------------------------------
9551 
9552 void __fastcall TInterface::SelectLengthsMenuItemClick(TObject *Sender)
9553 {
9554  try
9555  {
9556  TrainController->LogEvent("SelectLengthsMenuItemClick");
9557  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectLengthsMenuItemClick");
9558  TrackElementPanel->Visible = false;
9559  TrackLengthPanel->Visible = true;
9560  TrackLengthPanel->SetFocus();
9561  SelectLengthsFlag = true;
9562  InfoPanel->Visible = true;
9563  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Set values or leave blank for no change";
9565  {
9566  ShowMessage("Note: length value will apply to each element's track within the selection.\n\nThis message will not be shown again.");
9567  LengthWarningSentFlag = true;
9568  }
9569  DistanceBox->Text = "";
9570  SpeedLimitBox->Text = "";
9573  ResetChangedFileDataAndCaption(19, true); // true for NonPrefDirChangesMade
9574  Utilities->CallLogPop(1414);
9575  }
9576  catch(const Exception &e)
9577  {
9578  ErrorLog(154, e.Message);
9579  }
9580 }
9581 
9582 // ---------------------------------------------------------------------------
9583 
9584 void __fastcall TInterface::SelectBiDirPrefDirsMenuItemClick(TObject *Sender)
9585 {
9586 /* SelectVector contains all the track elements (and inactive elements but don't need them), so create up to 4 PrefDir
9587  elements from each one, and add each into ConstructPrefDir, then when all added use ConsolidatePrefDirs to add to EveryPrefDir
9588 */
9589  try
9590  {
9591  TrainController->LogEvent("SelectBiDirPrefDirsMenuItemClick");
9592  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectBiDirPrefDirsMenuItemClick");
9594  bool FoundFlag = false;
9595  if(Track->SelectVector.empty())
9596  {
9597  Utilities->CallLogPop(1550);
9598  return;
9599  }
9600  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9601  {
9602  TTrackElement TE = Track->SelectVectorAt(14, x);
9603  int VecPos = Track->GetVectorPositionFromTrackMap(42, TE.HLoc, TE.VLoc, FoundFlag);
9604  if(FoundFlag)
9605  {
9606  if((TE.TrackType == Points) || (TE.TrackType == Bridge) || (TE.TrackType == Crossover)) // 2-track element
9607  {
9608  TPrefDirElement PE0(TE, TE.Link[0], 0, TE.Link[1], 1, VecPos);
9610  TPrefDirElement PE1(TE, TE.Link[1], 1, TE.Link[0], 0, VecPos);
9612  TPrefDirElement PE2(TE, TE.Link[2], 2, TE.Link[3], 3, VecPos);
9614  TPrefDirElement PE3(TE, TE.Link[3], 3, TE.Link[2], 2, VecPos);
9616  }
9617  else if((TE.TrackType == Simple) || (TE.TrackType == Buffers) || (TE.TrackType == SignalPost) || (TE.TrackType == Continuation) ||
9618  (TE.TrackType == GapJump) || (TE.TrackType == FootCrossing))
9619  // need to list these explicitly since inactive elements will still be 'found' if there is an active element
9620  // at the same position
9621  {
9622  TPrefDirElement PE0(TE, TE.Link[0], 0, TE.Link[1], 1, VecPos);
9624  TPrefDirElement PE1(TE, TE.Link[1], 1, TE.Link[0], 0, VecPos);
9626  }
9627  }
9628  }
9630  ResetChangedFileDataAndCaption(22, false);
9631  // RlyFile = false; - don't alter this just for PrefDir changes
9632  Level1Mode = BaseMode; // call this first to clear everything, then set PrefDir mode
9633  SetLevel1Mode(30);
9635  SetLevel1Mode(31); // calls Clearand... to display all PrefDirs
9636  Utilities->CallLogPop(1549);
9637  }
9638  catch(const Exception &e)
9639  {
9640  ErrorLog(155, e.Message);
9641  }
9642 }
9643 
9644 // ---------------------------------------------------------------------------
9645 void __fastcall TInterface::CancelSelectionMenuItemClick(TObject *Sender)
9646 {
9647  try
9648  {
9649  TrainController->LogEvent("CancelSelectionClick");
9650  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CancelSelectionClick");
9651  ClearandRebuildRailway(46); // to remove the selection outline
9652  SelectionValid = false;
9653  Track->CopyFlag = false;
9655  ResetSelectRect();
9656  if(Level1Mode == TrackMode)
9657  {
9658  SetLevel1Mode(76);
9660  SetLevel2TrackMode(39);
9661  }
9662  else if(Level1Mode == PrefDirMode)
9663  {
9664  SetLevel1Mode(32);
9665  }
9666  Utilities->CallLogPop(1413);
9667  }
9668  catch(const Exception &e)
9669  {
9670  ErrorLog(156, e.Message);
9671  }
9672 }
9673 
9674 // ---------------------------------------------------------------------------
9675 void __fastcall TInterface::LoadTimetableMenuItemClick(TObject *Sender)
9676 {
9677  try
9678  {
9679  TrainController->LogEvent("LoadTimetableMenuItemClick");
9680  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LoadTimetableMenuItemClick");
9681  TimetableDialog->Filter = "Timetable file (*.ttb)|*.ttb";
9682  // reset all message flags, stops them being given twice new at v2.4.0
9683  TrainController->SSHigh = false;
9684  TrainController->MRSHigh = false;
9685  TrainController->MRSLow = false;
9686  TrainController->MassHigh = false;
9687  TrainController->BFHigh = false;
9688  TrainController->BFLow = false;
9689  TrainController->PwrHigh = false;
9690  TrainController->SigSHigh = false;
9691  TrainController->SigSLow = false;
9692  if(TimetableDialog->Execute())
9693  {
9694  if(TimetableDialog->InitialDir != TPath::GetDirectoryName(TimetableDialog->FileName))//new at v2.6.0 to retain a new directory
9695  {
9696  TimetableDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
9697  SaveTTDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
9698  }
9699  TrainController->LogEvent("LoadTimetable " + TimetableDialog->FileName);
9700  bool CheckLocationsExistInRailwayTrue = true;
9701  if(TrainController->TimetableIntegrityCheck(0, AnsiString(TimetableDialog->FileName).c_str(), true, CheckLocationsExistInRailwayTrue))
9702  // true for GiveMessages
9703  {
9704  Screen->Cursor = TCursor(-11); // Hourglass;
9705  std::ifstream TTBLFile(AnsiString(TimetableDialog->FileName).c_str(), std::ios_base::binary);
9706  if(TTBLFile.is_open())
9707  {
9708  bool SessionFileFalse = false;
9709  if(BuildTrainDataVectorForLoadFile(0, TTBLFile, true, CheckLocationsExistInRailwayTrue, SessionFileFalse)) // true for GiveMessages
9710  {
9711  SaveTempTimetableFile(0, TimetableDialog->FileName);
9712  } // don't need an 'else' as messages given in BuildTrainDataVectorForLoadFile
9713  }
9714  else
9715  {
9716  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
9717  }
9718  Screen->Cursor = TCursor(-2); // Arrow
9719  } // if(TimetableIntegrityCheck
9720  else
9721  ShowMessage("Timetable preliminary integrity check failed - unable to load");
9722  } // if(TimetableDialog->Execute())
9723  // else ShowMessage("Load Aborted");
9724  Utilities->CallLogPop(752);
9725  }
9726  catch(const Exception &e)
9727  {
9728  ErrorLog(34, e.Message);
9729  }
9730 }
9731 
9732 // ---------------------------------------------------------------------------
9733 void __fastcall TInterface::TakeSignallerControlMenuItemClick(TObject *Sender)
9734 {
9735  try
9736  {
9737  TrainController->LogEvent("SignallerControl1Click");
9738  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SignallerControl1Click");
9740  Train.SignallerStoppingFlag = false;
9741  Train.TrainMode = Signaller;
9742  if(Train.MaxRunningSpeed > Train.SignallerMaxSpeed)
9743  {
9744  Train.MaxRunningSpeed = Train.SignallerMaxSpeed;
9745  }
9746  if(Train.Stopped())
9747  Train.SignallerStopped = true; // condition added at v2.4.0 to allow for taking sig control of failed moving trains
9748  Train.CallingOnFlag = false; // in case was set, wouldn't start anyway if called on as SignallerStopped = true
9750  Train.PlotTrain(5, Display);
9751  AnsiString LocName = "";
9752  if(Train.LeadElement > -1)
9753  {
9754  LocName = Track->TrackElementAt(633, Train.LeadElement).ActiveTrackElementName;
9755  }
9756  if((LocName == "") && (Train.MidElement > -1))
9757  {
9758  LocName = Track->TrackElementAt(634, Train.MidElement).ActiveTrackElementName;
9759  }
9760 
9761  // store the value that allow restoration of tt control or not - RestoreTimetableLocation
9762  if(Train.StoppedAtLocation && (LocName != ""))
9763  {
9764  Train.RestoreTimetableLocation = LocName;
9765  }
9766  else
9767  {
9768  Train.RestoreTimetableLocation = "";
9769  }
9770 
9771  // check whether need to offer 'pass red signal'
9772  if(!Train.StoppedAtSignal && Train.StoppedAtLocation)
9773  {
9774  int NextElementPosition = Track->TrackElementAt(775, Train.LeadElement).Conn[Train.LeadExitPos];
9775  int NextEntryPos = Track->TrackElementAt(776, Train.LeadElement).ConnLinkPos[Train.LeadExitPos];
9776  if((NextElementPosition > -1) && (NextEntryPos > -1))
9777  {
9778  if((Track->TrackElementAt(777, NextElementPosition).Config[Track->GetNonPointsOppositeLinkPos(NextEntryPos)] == Signal) &&
9779  (Track->TrackElementAt(778, NextElementPosition).Attribute == 0))
9780  { // set both StoppedAtLocation & StoppedAtSignal, so that 'pass red signal' is offered in popup menu rather than move
9781  // forwards, but don't change the background colour so still shows as stopped at location
9782  Train.StoppedAtSignal = true;
9783  }
9784  }
9785  }
9786  // find element ID if no locname
9787  if((LocName == "") && Train.LeadElement > -1)
9788  {
9789  LocName = Track->TrackElementAt(635, Train.LeadElement).ElementID;
9790  }
9791  if((LocName == "") && (Train.MidElement > -1))
9792  {
9793  LocName = Track->TrackElementAt(636, Train.MidElement).ElementID;
9794  }
9795  Train.LogAction(0, Train.HeadCode, "", TakeSignallerControl, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
9796  Utilities->CallLogPop(1772);
9797  }
9798  catch(const Exception &e)
9799  {
9800  ErrorLog(157, e.Message);
9801  }
9802 }
9803 
9804 // ---------------------------------------------------------------------------
9805 
9806 void __fastcall TInterface::TimetableControlMenuItemClick(TObject *Sender)
9807 {
9808  try
9809  {
9810  TrainController->LogEvent("TimetableControlMenuItemClick");
9811  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TimetableControlMenuItemClick");
9813  Train.SignallerStoppingFlag = false;
9814  Train.TrainMode = Timetable;
9815  Train.SignallerStopped = false;
9816  Train.StoppedAfterSPAD = false;
9817  Train.SPADFlag = false;
9820 // red headcode[0]
9821  Train.PlotTrain(6, Display);
9822  AnsiString LocName = "";
9823  if(Train.LeadElement > -1)
9824  {
9825  LocName = Track->TrackElementAt(645, Train.LeadElement).ActiveTrackElementName;
9826  }
9827  if((LocName == "") && (Train.MidElement > -1))
9828  {
9829  LocName = Track->TrackElementAt(647, Train.MidElement).ActiveTrackElementName;
9830  }
9831  if((LocName == "") && Train.LeadElement > -1)
9832  {
9833  LocName = Track->TrackElementAt(646, Train.LeadElement).ElementID;
9834  }
9835  if((LocName == "") && (Train.MidElement > -1))
9836  {
9837  LocName = Track->TrackElementAt(648, Train.MidElement).ElementID;
9838  }
9839  if((Train.ActionVectorEntryPtr->LocationType == AtLocation) && (LocName == Train.ActionVectorEntryPtr->LocationName))
9840  {
9841  Train.StoppedAtLocation = true;
9842  Train.LastActionTime = TrainController->TTClockTime; // by itself this only affects trains that have still to arrive, if waiting to
9843  // depart the departure time & TRS time have already been calculated so need to
9844  // force a recalculation - see below
9845  Train.DepartureTimeSet = false; // force it to be recalculated based on new LastActionTime (if waiting to arrive this is false anyway)
9846  if(!Train.TrainFailed)
9847  {
9849  }
9850  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9851  if((Train.ActionVectorEntryPtr->FormatType == TimeLoc) && (Train.ActionVectorEntryPtr->ArrivalTime >= TDateTime(0)))
9852  { // Timetable indicates that train still waiting to arrive for a TimeLoc arrival so send message and mark as arrived
9853  Train.LogAction(28, Train.HeadCode, "", Arrive, LocName, Train.ActionVectorEntryPtr->ArrivalTime, Train.ActionVectorEntryPtr->Warning);
9854  Train.ActionVectorEntryPtr++; // advance pointer past arrival //added at v1.2.0
9855  }
9856  else if((Train.ActionVectorEntryPtr->FormatType == TimeTimeLoc) && !(Train.TimeTimeLocArrived))
9857  { // Timetable indicates that train still waiting to arrive for a TimeTimeLoc arrival so send message and mark as arrived
9858  Train.LogAction(29, Train.HeadCode, "", Arrive, LocName, Train.ActionVectorEntryPtr->ArrivalTime, Train.ActionVectorEntryPtr->Warning);
9859  Train.TimeTimeLocArrived = true;
9860  // NB: No need for 'Train.ActionVectorEntryPtr++' because still to act on the departure time
9861  }
9862  }
9863  else
9864  {
9865  int NextElementPos = -1; // addition for v1.3.2 due to Carwyn Thomas error
9866  int NextEntryPos = -1; // ---ditto---
9867  if(Train.LeadElement > -1) // ---ditto---
9868  { // ---ditto---
9869  NextElementPos = Track->TrackElementAt(658, Train.LeadElement).Conn[Train.LeadExitPos]; // had 'int' prefix before additions
9870  NextEntryPos = Track->TrackElementAt(659, Train.LeadElement).ConnLinkPos[Train.LeadExitPos]; // ---ditto---
9871  } // ---ditto---
9872  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9873  if(!Train.TrainFailed)
9874  {
9875  Train.PlotTrainWithNewBackgroundColour(31, clNormalBackground, Display); // to remove other background if was present, moved from
9876  } // within Train.AbleToMove at v2.4.0 to cancel signal stop background
9877  if(Train.AbleToMove(1)) // if has no power
9878  {
9879  Train.EntrySpeed = 0; // moved from below for v1.3.2 after Carwyn Thomas error
9880  Train.EntryTime = TrainController->TTClockTime; // ---Ditto---
9881  Train.FirstHalfMove = true; // ---Ditto---
9882  if((NextElementPos > -1) && (NextEntryPos > -1)) // changed from if(NextElementPos >= 0) as above
9883  {
9884  // Train.EntrySpeed = 0;
9885  // Train.EntryTime = TrainController->TTClockTime;
9886  // Train.FirstHalfMove = true;
9887  Train.SetTrainMovementValues(15, NextElementPos, NextEntryPos);
9888  }
9889  // else follow the continuations //added these 3 conditions for v1.3.2 after Carwyn Thomas error
9890  else if((Train.LeadElement > -1) && (Track->TrackElementAt(894, Train.LeadElement).TrackType == Continuation))
9891  {
9892  Train.SetTrainMovementValues(21, Train.LeadElement, Train.LeadEntryPos); // Use LeadElement for calcs if lead is a continuation
9893  }
9894  else if((Train.MidElement > -1) && (Track->TrackElementAt(895, Train.MidElement).TrackType == Continuation))
9895  {
9896  Train.SetTrainMovementValues(22, Train.MidElement, Train.MidEntryPos); // Use MidElement for calcs if Mid is a continuation
9897  }
9898  else if((Train.LagElement > -1) && (Track->TrackElementAt(896, Train.LagElement).TrackType == Continuation))
9899  {
9900  Train.SetTrainMovementValues(23, Train.LagElement, Train.LagEntryPos); // Use LagElement for calcs if Lag is a continuation
9901  }
9902  }
9903  else if(Train.StoppedAtSignal)
9904  {
9905  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9906  if(!Train.TrainFailed)
9907  {
9909  }
9910  // TrainController->LogActionError(42, Train.HeadCode, "", SignalHold, Track->TrackElementAt(757, NextElementPos).ElementID);
9911  }
9912  }
9913  Train.LogAction(1, Train.HeadCode, "", RestoreTimetableControl, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
9914  Utilities->CallLogPop(1195);
9915  }
9916  catch(const Exception &e)
9917  {
9918  ErrorLog(158, e.Message);
9919  }
9920 }
9921 
9922 // ---------------------------------------------------------------------------
9923 
9924 void __fastcall TInterface::ChangeDirectionMenuItemClick(TObject *Sender)
9925 {
9926  try
9927  {
9928  TrainController->LogEvent("ChangeDirectionMenuItemClick");
9929  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ChangeDirectionMenuItemClick");
9931  Train.SignallerStoppingFlag = false;
9932  Train.SignallerChangeTrainDirection(0); // this unplots & replots train, which checks for facing signal and sets StoppedAtSignal if req'd
9933  Train.SignallerStopped = true;
9934  AnsiString LocName = "";
9935  if(Train.LeadElement > -1)
9936  {
9937  LocName = Track->TrackElementAt(637, Train.LeadElement).ActiveTrackElementName;
9938  }
9939  if((LocName == "") && (Train.MidElement > -1))
9940  {
9941  LocName = Track->TrackElementAt(638, Train.MidElement).ActiveTrackElementName;
9942  }
9943  if((LocName == "") && Train.LeadElement > -1)
9944  {
9945  LocName = Track->TrackElementAt(639, Train.LeadElement).ElementID;
9946  }
9947  if((LocName == "") && (Train.MidElement > -1))
9948  {
9949  LocName = Track->TrackElementAt(640, Train.MidElement).ElementID;
9950  }
9951  Train.LogAction(2, Train.HeadCode, "", SignallerChangeDirection, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
9952  Utilities->CallLogPop(1196);
9953  }
9954  catch(const Exception &e)
9955  {
9956  ErrorLog(159, e.Message);
9957  }
9958 }
9959 // ---------------------------------------------------------------------------
9960 
9961 void __fastcall TInterface::MoveForwardsMenuItemClick(TObject *Sender)
9962 {
9963  try
9964  {
9965  TrainController->LogEvent("MoveForwardsMenuItemClick");
9966  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveForwardsMenuItemClick");
9968  Train.SignallerStoppingFlag = false;
9969  if(!Train.AbleToMove(2))
9970  { // shouldn't be here as when unable to move MoveForwards shouldn't be enabled, but leave in as a precaution
9971  Utilities->CallLogPop(1197);
9972  return;
9973  }
9974  Train.SignallerStopped = false;
9975  Train.StoppedAfterSPAD = false; // in case had been set
9976  Train.SPADFlag = false;
9977  Train.StoppedAtLocation = false; // may not have been set but reset anyway
9978  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9980  Train.EntrySpeed = 0;
9982  Train.FirstHalfMove = true;
9983  int NextElementPos = -1; // addition for v1.3.2 due to Carwyn Thomas error
9984  int NextEntryPos = -1; // ---ditto---
9985  if(Train.LeadElement > -1) // ---ditto---
9986  { // ---ditto---
9987  NextElementPos = Track->TrackElementAt(652, Train.LeadElement).Conn[Train.LeadExitPos]; // had 'int' prefix before additions
9988  NextEntryPos = Track->TrackElementAt(657, Train.LeadElement).ConnLinkPos[Train.LeadExitPos]; // ---ditto---
9989  } // ---ditto---
9990  if((NextElementPos > -1) && (NextEntryPos > -1))
9991  {
9992  Train.SetTrainMovementValues(14, NextElementPos, NextEntryPos); // NextElement is the element to be entered
9993  }
9994  // else follow the continuations
9995  else if((Train.LeadElement > -1) && (Track->TrackElementAt(784, Train.LeadElement).TrackType == Continuation))
9996  {
9997  Train.SetTrainMovementValues(17, Train.LeadElement, Train.LeadEntryPos); // Use LeadElement for calcs if lead is a continuation
9998  }
9999  else if((Train.MidElement > -1) && (Track->TrackElementAt(785, Train.MidElement).TrackType == Continuation))
10000  {
10001  Train.SetTrainMovementValues(18, Train.MidElement, Train.MidEntryPos); // Use MidElement for calcs if Mid is a continuation
10002  }
10003  else if((Train.LagElement > -1) && (Track->TrackElementAt(786, Train.LagElement).TrackType == Continuation))
10004  {
10005  Train.SetTrainMovementValues(19, Train.LagElement, Train.LagEntryPos); // Use LagElement for calcs if Lag is a continuation
10006  }
10007  Train.LogAction(3, Train.HeadCode, "", SignallerMoveForwards, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10008  Utilities->CallLogPop(1198);
10009  }
10010  catch(const Exception &e)
10011  {
10012  ErrorLog(160, e.Message);
10013  }
10014 }
10015 // ---------------------------------------------------------------------------
10016 
10017 void __fastcall TInterface::SignallerJoinedByMenuItemClick(TObject *Sender)
10018 { // new at v2.4.0
10019  try
10020  {
10021  TrainController->LogEvent("JoinedByMenuItemClick");
10022  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",JoinedByMenuItemClick");
10023  TTrain *TrainToBeJoinedBy;
10025  if(ThisTrain.IsThereAnAdjacentTrain(1, TrainToBeJoinedBy)) // this must come before both powers zero check in order to set a valid TrainToBeJoinedBy
10026  {
10027  if(TrainToBeJoinedBy->TrainMode != Signaller)
10028  {
10029  TrainController->StopTTClockMessage(91, "Adjacent train must be under signaller control in order to join");
10030  Utilities->CallLogPop(2156);
10031  return;
10032  }
10033  // here if there is an adjacent train under signaller control
10034  if((TrainToBeJoinedBy->PowerAtRail < 1) && (ThisTrain.PowerAtRail < 1))
10035  {
10036  ShowMessage("Can't join two trains when both are without power");
10037  Utilities->CallLogPop(2157);
10038  return;
10039  }
10040  AnsiString TrainToBeJoinedByHeadCode = TrainToBeJoinedBy->HeadCode;
10041  // set new values for mass etc
10042  double OtherBrakeForce = TrainToBeJoinedBy->MaxBrakeRate * TrainToBeJoinedBy->Mass;
10043  double OwnBrakeForce = ThisTrain.MaxBrakeRate * ThisTrain.Mass;
10044  double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->Mass + ThisTrain.Mass);
10045  ThisTrain.Mass += TrainToBeJoinedBy->Mass;
10046  ThisTrain.MaxBrakeRate = CombinedBrakeRate;
10047  ThisTrain.PowerAtRail += TrainToBeJoinedBy->PowerAtRail;
10048  ThisTrain.AValue = sqrt(2 * ThisTrain.PowerAtRail / ThisTrain.Mass);
10049 
10050  TrainToBeJoinedBy->TrainGone = true; // this will cause other train to be deleted
10051  TrainToBeJoinedBy->JoinedOtherTrainFlag = true;
10052  AnsiString LocName = "";
10053  if(ThisTrain.LeadElement > -1)
10054  {
10055  LocName = Track->TrackElementAt(979, ThisTrain.LeadElement).ActiveTrackElementName;
10056  }
10057  if((LocName == "") && (ThisTrain.MidElement > -1))
10058  {
10059  LocName = Track->TrackElementAt(980, ThisTrain.MidElement).ActiveTrackElementName;
10060  }
10061  if((LocName == "") && ThisTrain.LeadElement > -1)
10062  {
10063  LocName = Track->TrackElementAt(981, ThisTrain.LeadElement).ElementID;
10064  }
10065  if((LocName == "") && (ThisTrain.MidElement > -1))
10066  {
10067  LocName = Track->TrackElementAt(982, ThisTrain.MidElement).ElementID;
10068  }
10069  ThisTrain.StoppedWithoutPower = true;
10070  if(ThisTrain.PowerAtRail >= 1)
10071  {
10072  ThisTrain.StoppedWithoutPower = false;
10073  }
10074  ThisTrain.TrainFailed = false; // if had failed then no longer failed, even if joining train has no power
10075  if(!ThisTrain.StoppedAtLocation)
10076  {
10077  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10079  }
10080  else
10081  {
10082  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10084  }
10085  ThisTrain.SignallerStopped = true; // maybe as well as stopped without power, thought that takes precedence in floating window
10086  ThisTrain.LogAction(34, ThisTrain.HeadCode, TrainToBeJoinedBy->HeadCode, SignallerJoin, LocName, TDateTime(0), false); // TDateTime isn't used
10087  ThisTrain.ZeroPowerNoFrontSplitMessage = false; // added at v2.4.0, no need to include TrainToBeJoinedBy as that will be removed
10088  ThisTrain.ZeroPowerNoRearSplitMessage = false;
10089  ThisTrain.FailedTrainNoFinishJoinMessage = false;
10090  ThisTrain.ZeroPowerNoJoinedByMessage = false;
10091  ThisTrain.ZeroPowerNoCDTMessage = false;
10092  ThisTrain.ZeroPowerNoNewServiceMessage = false;
10094  ThisTrain.ZeroPowerNoRepeatShuttleMessage = false;
10096  Utilities->CallLogPop(2158);
10097  }
10098  }
10099  catch(const Exception &e)
10100  {
10101  ErrorLog(207, e.Message);
10102  }
10103 }
10104 // ---------------------------------------------------------------------------
10105 
10106 void __fastcall TInterface::RepairFailedTrainMenuItemClick(TObject *Sender)
10107 { // added at v2.4.0
10108  try
10109  {
10110  TrainController->LogEvent("RepairFailedTrainMenuItemClick");
10111  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RepairFailedTrainMenuItemClick");
10113  Train.TrainFailed = false;
10114  Train.StoppedWithoutPower = false;
10115  Train.SignallerStopped = true;
10116  if(!Train.StoppedAtLocation)
10117  {
10118  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10120  }
10121  else
10122  {
10123  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10125  }
10126  Train.PowerAtRail = Train.OriginalPowerAtRail; // recover from original value, new at v2.4.0
10127  Train.AValue = sqrt(2 * Train.PowerAtRail / Train.Mass);
10128  Train.SetTrainMovementValues(24, Train.LeadElement, Train.LeadEntryPos);
10129  AnsiString LocName = "";
10130  if(Train.LeadElement > -1)
10131  {
10132  LocName = Track->TrackElementAt(983, Train.LeadElement).ActiveTrackElementName;
10133  }
10134  if((LocName == "") && (Train.MidElement > -1))
10135  {
10136  LocName = Track->TrackElementAt(984, Train.MidElement).ActiveTrackElementName;
10137  }
10138  if((LocName == "") && Train.LeadElement > -1)
10139  {
10140  LocName = Track->TrackElementAt(985, Train.LeadElement).ElementID;
10141  }
10142  if((LocName == "") && (Train.MidElement > -1))
10143  {
10144  LocName = Track->TrackElementAt(986, Train.MidElement).ElementID;
10145  }
10146  Train.LogAction(35, Train.HeadCode, "", RepairFailedTrain, LocName, TrainController->TTClockTime, false); // false for no warning
10147  Train.ZeroPowerNoFrontSplitMessage = false;
10148  Train.ZeroPowerNoRearSplitMessage = false;
10149  Train.FailedTrainNoFinishJoinMessage = false;
10150  Train.ZeroPowerNoJoinedByMessage = false;
10151  Train.ZeroPowerNoCDTMessage = false;
10152  Train.ZeroPowerNoNewServiceMessage = false;
10154  Train.ZeroPowerNoRepeatShuttleMessage = false;
10156  Utilities->CallLogPop(2159);
10157  }
10158  catch(const Exception &e)
10159  {
10160  ErrorLog(208, e.Message);
10161  }
10162 }
10163 
10164 // ---------------------------------------------------------------------------
10165 
10166 void __fastcall TInterface::SignallerControlStopMenuItemClick(TObject *Sender)
10167 {
10168  try
10169  {
10170  TrainController->LogEvent("SignallerControlStopMenuItemClick");
10171  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SignallerControlStopMenuItemClick");
10174  if(Train.LeadElement > -1)
10175  {
10176  if(Track->TrackElementAt(787, Train.LeadElement).Conn[Train.LeadExitPos] > -1)
10177  {
10178  Train.SignallerStoppingFlag = true;
10179  Train.SignallerStopBrakeRate = 0;
10180  Train.LogAction(24, Train.HeadCode, "", SignallerControlStop, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10181  }
10182  else
10184  }
10185  else
10187  Utilities->CallLogPop(1553);
10188  }
10189  catch(const Exception &e)
10190  {
10191  ErrorLog(161, e.Message);
10192  }
10193 }
10194 
10195 // ---------------------------------------------------------------------------
10196 void __fastcall TInterface::PassRedSignalMenuItemClick(TObject *Sender)
10197 {
10198  try
10199  {
10200  TrainController->LogEvent("PassRedSignalMenuItemClick");
10201  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PassRedSignalMenuItemClick");
10203  Train.SignallerStoppingFlag = false;
10204  int NextElementPos = Track->TrackElementAt(712, Train.LeadElement).Conn[Train.LeadExitPos];
10205  if(NextElementPos < 0)
10206  {
10207  throw Exception("Error, no element in front in PassRedSignalMenuItemClick");
10208  }
10209  TTrackElement &TrackElement = Track->TrackElementAt(653, NextElementPos);
10210 /* drop this error as may be some circumstances where behind a signal in sig mode but not stopped at signal
10211  if(!Train.StoppedAtSignal)
10212  {
10213  throw Exception("Error, not StoppedAtSignal in PassRedSignalMenuItemClick");
10214  }
10215 */
10216  if(TrackElement.TrackType != SignalPost)
10217  {
10218  throw Exception("Error, next element not a signal type in PassRedSignalMenuItemClick");
10219  }
10220  Train.SignallerStopped = false;
10221  Train.StoppedAtLocation = false; // may have started at station in signaller mode and also at a red signal, in this case both SignallerStopped
10222  // and StoppedAtLocation are set but the background colour stays pale green for station, not signal,
10223  // since no need to alert the user
10224  Train.StoppedAfterSPAD = false; // in case had been set
10225  Train.SPADFlag = false;
10226  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10228  Train.AllowedToPassRedSignal = true;
10229  Train.LogAction(4, Train.HeadCode, "", SignallerPassRedSignal, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10230  Utilities->CallLogPop(1199);
10231  }
10232  catch(const Exception &e)
10233  {
10234  ErrorLog(162, e.Message);
10235  }
10236 }
10237 // ---------------------------------------------------------------------------
10238 
10239 void __fastcall TInterface::StepForwardMenuItemClick(TObject *Sender)
10240 {
10241  try
10242  {
10243  TrainController->LogEvent("StepForwardMenuItemClick");
10244  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",StepForwardMenuItemClick");
10246  Train.SignallerStoppingFlag = false;
10247  Train.SignallerStopped = false;
10248  Train.StoppedAtLocation = false; // may have started at station in signaller mode and also at a red signal, in this case both SignallerStopped
10249  // and StoppedAtLocation are set but the background colour stays pale green for station, not signal,
10250  // since no need to alert the user
10251  Train.StoppedAfterSPAD = false; // in case had been set
10252  Train.SPADFlag = false;
10253  Train.StepForwardFlag = true;
10254  Train.AllowedToPassRedSignal = true; // in case at a signal, will clear when half-way into next element whether a signal or not
10255  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10257  Train.LogAction(32, Train.HeadCode, "", SignallerStepForward, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10258  int NextElementPos = -1;
10259 // addition for v1.3.2 due to Carwyn Thomas error: can't select StepForwardMenuItem if exiting at a continuation but leave this in anyway
10260  int NextEntryPos = -1; // ---ditto---
10261  if(Train.LeadElement > -1) // ---ditto---
10262  { // ---ditto---
10263  NextElementPos = Track->TrackElementAt(804, Train.LeadElement).Conn[Train.LeadExitPos]; // had 'int' prefix before additions
10264  NextEntryPos = Track->TrackElementAt(805, Train.LeadElement).ConnLinkPos[Train.LeadExitPos]; // ---ditto---
10265  } // ---ditto---
10266  if((NextElementPos > -1) && (NextEntryPos > -1))
10267  { // call this after StepForwardFlag set
10268  Train.EntrySpeed = 0;
10270  Train.FirstHalfMove = true;
10271  Train.SetTrainMovementValues(20, NextElementPos, NextEntryPos); // NextElement is the element to be entered
10272  }
10273  Utilities->CallLogPop(1800);
10274  }
10275  catch(const Exception &e)
10276  {
10277  ErrorLog(163, e.Message);
10278  }
10279 }
10280 
10281 // ---------------------------------------------------------------------------
10282 
10283 void __fastcall TInterface::RemoveTrainMenuItemClick(TObject *Sender)
10284 {
10285  try
10286  {
10287  TrainController->LogEvent("RemoveTrainMenuItemClick");
10288  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RemoveTrainMenuItemClick");
10290  if((!Train.Derailed) && (!Train.Crashed))
10291  {
10292  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
10294  UnicodeString Message = UnicodeString(Train.HeadCode) + " will be removed from the railway - proceed?";
10295  int button = Application->MessageBox(Message.c_str(), L"Please confirm", MB_YESNO);
10296  TrainController->BaseTime = TDateTime::CurrentDateTime();
10298  if(button == IDNO)
10299  {
10300  Utilities->CallLogPop(1801);
10301  return;
10302  }
10303  }
10304  Train.SignallerStoppingFlag = false;
10305  Train.TrainGone = true; // will be removed by TTrainController::Operate
10306  Train.SignallerRemoved = true;
10307  Train.TrainDataEntryPtr->TrainOperatingDataVector.at(Train.RepeatNumber).RunningEntry = Exited;
10308  AnsiString LocName = "";
10309  if(Train.LeadElement > -1)
10310  {
10311  LocName = Track->TrackElementAt(641, Train.LeadElement).ActiveTrackElementName;
10312  }
10313  if((LocName == "") && (Train.MidElement > -1))
10314  {
10315  LocName = Track->TrackElementAt(642, Train.MidElement).ActiveTrackElementName;
10316  }
10317  if((LocName == "") && Train.LeadElement > -1)
10318  {
10319  LocName = Track->TrackElementAt(643, Train.LeadElement).ElementID;
10320  }
10321  if((LocName == "") && (Train.MidElement > -1))
10322  {
10323  LocName = Track->TrackElementAt(644, Train.MidElement).ElementID;
10324  }
10325  TTrackElement *TrackElementPtr;
10326  int RouteNumber;
10327  TAllRoutes::TRouteType RouteType;
10328  if(Train.LeadElement > -1)
10329  {
10330  TrackElementPtr = &(Track->TrackElementAt(673, Train.LeadElement));
10331  // remove TrainIDs from track element, added at v2.4.0
10332  if(TrackElementPtr->TrackType == Bridge)
10333  {
10334  if(Train.LeadExitPos > 1)
10335  {
10336  TrackElementPtr->TrainIDOnBridgeTrackPos23 = -1;
10337  }
10338  else
10339  {
10340  TrackElementPtr->TrainIDOnBridgeTrackPos01 = -1;
10341  }
10342  }
10343  else
10344  {
10345  TrackElementPtr->TrainIDOnElement = -1;
10346  }
10347  // reset any CallingOnSet flags for signals, if facing wrong way doesn't matter, shouldn't be set anyay
10348  if((TrackElementPtr->TrackType == SignalPost) && TrackElementPtr->CallingOnSet)
10349  {
10350  TrackElementPtr->CallingOnSet = false;
10351  Track->PlotSignal(6, *TrackElementPtr, Display);
10352  }
10353 // [added at v1.3.0] here check if on an automatic signals route and if so reset signals for the entire route from the
10354 // start of the route - after the train has been removed, use LeadElement and also MidElement (if no autosigs route at LeadElement) just to be sure
10355  RouteType = AllRoutes->GetRouteTypeAndNumber(27, Train.LeadElement, Train.LeadEntryPos, RouteNumber);
10356  if(RouteType == TAllRoutes::AutoSigsRoute)
10357  {
10360  }
10361 // end of addition
10362  }
10363  if(Train.MidElement > -1)
10364  {
10365  TrackElementPtr = &(Track->TrackElementAt(674, Train.MidElement));
10366  // remove TrainIDs from track element, added at v2.4.0
10367  if(TrackElementPtr->TrackType == Bridge)
10368  {
10369  if(Train.MidExitPos > 1)
10370  {
10371  TrackElementPtr->TrainIDOnBridgeTrackPos23 = -1;
10372  }
10373  else
10374  {
10375  TrackElementPtr->TrainIDOnBridgeTrackPos01 = -1;
10376  }
10377  }
10378  else
10379  {
10380  TrackElementPtr->TrainIDOnElement = -1;
10381  }
10382  if((TrackElementPtr->TrackType == SignalPost) && TrackElementPtr->CallingOnSet)
10383  {
10384  TrackElementPtr->CallingOnSet = false;
10385  Track->PlotSignal(7, *TrackElementPtr, Display);
10386  }
10387 // [added at v1.3.0 as above]
10389  {
10390  RouteType = AllRoutes->GetRouteTypeAndNumber(28, Train.MidElement, Train.MidEntryPos, RouteNumber);
10391  if(RouteType == TAllRoutes::AutoSigsRoute)
10392  {
10395  }
10396  }
10397 // end of addition
10398  }
10399  if(Train.LeadElement > -1)
10400  // addition for v1.3.2 after Carwyn Thomas fault reported 24/05/15 - need to check if exiting at continuation (LeadElement == -1) as if so fails at next line
10401  {
10402  if(Track->TrackElementAt(675, Train.LeadElement).Conn[Train.LeadExitPos] > -1)
10403  {
10404  TrackElementPtr = &(Track->TrackElementAt(676, Track->TrackElementAt(677, Train.LeadElement).Conn[Train.LeadExitPos]));
10405  if((TrackElementPtr->TrackType == SignalPost) && TrackElementPtr->CallingOnSet)
10406  {
10407  TrackElementPtr->CallingOnSet = false;
10408  Track->PlotSignal(8, *TrackElementPtr, Display);
10409  }
10410  }
10411  }
10412  Train.LogAction(5, Train.HeadCode, "", RemoveTrain, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10413  if(Train.ActionVectorEntryPtr->Command != "Frh") // if remaining at location no point in sending 'failed to terminate' message
10414  {
10415  Train.SendMissedActionLogs(0, -1, Train.ActionVectorEntryPtr); // -1 is a marker for send messages for all remaining
10416  } // entries, including Fer if present
10417  Utilities->CallLogPop(1200);
10418  }
10419  catch(const Exception &e)
10420  {
10421  ErrorLog(164, e.Message);
10422  }
10423 }
10424 
10425 // ---------------------------------------------------------------------------
10426 
10427 void __fastcall TInterface::ErrorButtonClick(TObject *Sender)
10428  // to terminate after error message given
10429 {
10430  ErrorMessage->Visible = false;
10431  ErrorMessageStoreImage->Visible = false;
10432  ErrorButton->Visible = false;
10433  Display->GetImage()->Visible = true;
10434  Application->Terminate();
10435 }
10436 
10437 // ---------------------------------------------------------------------------
10438 void __fastcall TInterface::PerformancePanelLabelStartDrag(TObject *Sender, TDragObject *&DragObject)
10439 {
10440  try
10441  {
10442  TrainController->LogEvent("PerformancePanelLabelStartDrag");
10443  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PerformancePanelLabelStartDrag");
10444  PerformancePanelDragStartX = Mouse->CursorPos.x - PerformancePanel->Left;
10445  PerformancePanelDragStartY = Mouse->CursorPos.y - PerformancePanel->Top;
10446  Utilities->CallLogPop(1202);
10447  }
10448  catch(const Exception &e)
10449  {
10450  ErrorLog(165, e.Message);
10451  }
10452 }
10453 // ---------------------------------------------------------------------------
10454 
10455 void __fastcall TInterface::FormClose(TObject *Sender, TCloseAction &Action)
10456 {
10457  try
10458  {
10459  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",FormClose");
10461  {
10462  UnicodeString MessageStr =
10463  "Note that leaving the track unlinked will cause preferred directions to be lost on reloading. Prevent by linking the track then resaving. Do you still wish to exit?";
10464  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
10465  if(button == IDNO)
10466  {
10467  Action = caNone; // prevents form & application from closing
10468  Utilities->CallLogPop(1712);
10469  return;
10470  }
10471  }
10473  {
10474  UnicodeString MessStr = "";
10476  {
10477  MessStr = UnicodeString("The railway and the timetable have both changed, exit without saving either?");
10478  }
10479  else if(FileChangedFlag)
10480  {
10481  MessStr = UnicodeString("The railway has changed, exit without saving?");
10482  }
10483  else
10484  {
10485  MessStr = UnicodeString("The timetable has changed, exit without saving?");
10486  }
10487  int button = Application->MessageBox(MessStr.c_str(), L"Please confirm", MB_YESNO);
10488  if(button == IDNO)
10489  {
10490  Action = caNone; // prevents form & application from closing
10491  Utilities->CallLogPop(1133);
10492  return;
10493  }
10494  }
10495 
10496  if(Level1Mode == OperMode)
10497  {
10499  {
10500  UnicodeString MessageStr = "Please note that the session will be lost if it hasn't been saved. Do you still wish to exit?";
10501  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
10503  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
10504  TrainController->BaseTime = TDateTime::CurrentDateTime();
10506  if(button == IDNO)
10507  {
10508  Action = caNone; // prevents form & application from closing
10509  Utilities->CallLogPop(969);
10510  return;
10511  }
10512  }
10514  Utilities->PerformanceFile.close();
10515  }
10516  if((TempTTFileName != "") && FileExists(TempTTFileName))
10517  {
10518  DeleteFile(TempTTFileName);
10519  }
10520  Utilities->CallLogPop(971);
10521  }
10522  catch(const Exception &e)
10523  {
10524  ErrorLog(166, e.Message);
10525  }
10526 }
10527 
10528 // ---------------------------------------------------------------------------
10529 
10530 void __fastcall TInterface::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
10531 {
10532 // TrainController->LogEvent("FormKeyDown," + AnsiString(Key));
10533 // drop event log as have too many spurious entries
10534  try
10535  {
10536  if((Shift.Contains(ssAlt)) && (Shift.Contains(ssCtrl)))
10537  {
10538  if(Key == '2')
10539  {
10540  if(CallLogTickerLabel->Visible)
10541  {
10542  CallLogTickerLabel->Visible = false;
10543  }
10544  else
10545  {
10546  CallLogTickerLabel->Visible = true;
10547  }
10548  }
10549  else if(Key == '3')
10550  {
10551  if(DevelopmentPanel->Visible)
10552  {
10553  DevelopmentPanel->Visible = false;
10554  }
10555  else
10556  {
10557  DevelopmentPanel->Visible = true;
10558  DevelopmentPanel->BringToFront();
10559  }
10560  }
10561  else if(Key == '4')
10562  {
10563  TestFunction();
10564  }
10565  else if(Key == '5')
10566  {
10567  TMsgDlgButtons Buttons;
10568  Buttons << mbYes << mbNo;
10569  if(MessageDlg("Do you wish to allow facing signals next to bridges? If so please be aware that routes cannot be truncated to these signals.", mtWarning, Buttons, 0) == mrYes)
10570  {
10572  }
10573  else
10574  {
10576  }
10577  }
10578  }
10579  else if(Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10580  {
10581  CtrlKey = true;
10582  }
10583  else if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
10584  {
10585  ShiftKey = true;
10586  }
10587 
10588 // below added at v1.3.0 to allow keyboard scrolling as well as mouse button scrolling - see user suggestion on Features & Requests forum 30/09/12
10589 // the NonCTRLOrSHIFTKeyUpFlag prevents repeated viewpoint movements without keys being re-pressed
10590 // note that use the OnKeyDown event rather than OnKeyPress as suggested by the user so that the CTRL & SHIFT keys can be taken into account
10591 
10592 //at v2.4.2 the flag changed to LastNonCtrlOrShiftKeyDown to make condition specific to last key, because when a message given the key up event
10593 //is not seen as the form does not have focus, so with the flag no shortcut key will work on the first press, with this only the same shortcut key
10594 //won't work on first press and that is less likely to be used a second time on either side of the message
10595 
10596  if((Key != VK_SHIFT) && (Key != VK_CONTROL))
10597  {
10598  if(LastNonCtrlOrShiftKeyDown == Key) //same key still down rejected
10599  {
10600  return;
10601  }
10602  else
10603  {
10605  }
10606  }
10607 
10608  if(Key == VK_UP)
10609  {
10610  if(ScreenUpButton->Enabled)
10611  ScreenUpButton->Click();
10612  }
10613  else if(Key == VK_DOWN)
10614  {
10615  if(ScreenDownButton->Enabled)
10616  ScreenDownButton->Click();
10617  }
10618  else if(Key == VK_LEFT)
10619  {
10620  if(ScreenLeftButton->Enabled)
10621  ScreenLeftButton->Click();
10622  }
10623  else if(Key == VK_RIGHT)
10624  {
10625  if(ScreenRightButton->Enabled)
10626  ScreenRightButton->Click();
10627  }
10628  else if(Key == VK_HOME)
10629  {
10630  if(HomeButton->Enabled)
10631  HomeButton->Click();
10632  }
10633 // end of 1.3.0 addition
10634  else if(Key == VK_END) // added at v2.2.0 to toggle zoom using 'End' key
10635  {
10636  if(ZoomButton->Enabled)
10637  ZoomButton->Click();
10638  }
10639  else if(Key == VK_END) // added at v2.2.0 to toggle zoom using 'End' key
10640  {
10641  if(ZoomButton->Enabled)
10642  ZoomButton->Click();
10643  }
10644 
10645 //below added for v2.4.2 to add more keyboard shortcuts
10646  if(DistanceBox->Focused() || SpeedLimitBox->Focused() || MileEdit->Focused() || ChainEdit->Focused() || YardEdit->Focused() || SpeedEditBox2->Focused()
10647  || MTBFEditBox->Focused() || LocationNameTextBox->Focused() || TextBox->Focused() || PowerEditBox->Focused() || SpeedEditBox->Focused()
10648  || AddSubMinsBox->Focused() || OneEntryTimetableMemo->Focused())
10649  {// prevent letter keys interfering when these boxes have focus - many are mutually exclusive but include them all
10650  return;
10651  }
10652 
10653  if(Shift.Contains(ssShift) && !Shift.Contains(ssAlt) && !Shift.Contains(ssCtrl) && NewHomeButton->Enabled && NewHomeButton->Visible)
10654  {
10655  if(Level1Mode != TimetableMode && (Key == 'H' || Key == 'h'))//TimetablePanel uses Shift H too so disable this when it's in use
10656  {
10657  NewHomeButton->Click();
10658  }
10659  }
10660 
10661 //Operating panel
10662  if(Level1Mode == OperMode && OperatingPanel->Enabled && OperatingPanel->Visible && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10663  { //use Shift.Contains(ssShift etc instead of ShiftKey as that not set if pressed second after Ctrl key pressed
10664  if(!Shift.Contains(ssCtrl))
10665  {
10666  if(OperateButton->Visible && OperateButton->Enabled)
10667  {
10668  if(Level2OperMode == Operating && (Key == 'P' || Key == 'p'))
10669  {
10670  OperateButton->Click();
10671  }
10672  else if((Level2OperMode == Paused || Level2OperMode == PreStart) && (Key == 'R' || Key == 'r'))
10673  {
10674  OperateButton->Click();
10675  }
10676  }
10677  if(PresetAutoSigRoutesButton->Visible && PresetAutoSigRoutesButton->Enabled && (Key == 'A' || Key == 'a'))
10678  {
10679  PresetAutoSigRoutesButton->Click();
10680  }
10681  if(PerformanceLogButton->Visible && PerformanceLogButton->Enabled && (Key == 'L' || Key == 'l'))
10682  {
10683  PerformanceLogButton->Click();
10684  }
10685  if(CallingOnButton->Visible && CallingOnButton->Enabled && (Key == 'O' || Key == 'o'))
10686  {
10687  CallingOnButton->Click();
10688  }
10689  if(OperatorActionButton->Visible && OperatorActionButton->Enabled && (Key == 'D' || Key == 'd'))
10690  {
10691  OperatorActionButton->Click();
10692  }
10693  if(RouteCancelButton->Visible && RouteCancelButton->Enabled && (Key == 'C' || Key == 'c'))
10694  {
10695  RouteCancelButton->Click();
10696  }
10697  if(TTClockAdjButton->Visible && TTClockAdjButton->Enabled && (Key == 'T' || Key == 't'))
10698  {
10699  TTClockAdjButton->Click();
10700  }
10701  if(AutoSigsButton->Visible && AutoSigsButton->Enabled && Key == '1') //route buttons - autosigs
10702  {
10703  AutoSigsButton->Click();
10704  }
10705  if(SigPrefButton->Visible && SigPrefButton->Enabled && Key == '2') //route buttons - prefdir
10706  {
10707  SigPrefButton->Click();
10708  }
10709  if(UnrestrictedButton->Visible && UnrestrictedButton->Enabled && Key == '3') //route buttons - unrestricted
10710  {
10711  UnrestrictedButton->Click();
10712  }
10713  if(ExitOperationButton->Visible && ExitOperationButton->Enabled && Key == '\x1b')
10714  {
10715  ExitOperationButton->Click();
10716  }
10717  }
10718  else //CtrlKey down
10719  {
10720  if(SaveSessionButton->Visible && SaveSessionButton->Enabled)
10721  {
10722  SaveMenuItem->ShortCut = 0; //It's normally 16467 (Ctrl S) & will be restored in FormKeyUp. Has to be reset or will grab the key combination
10723  if(Key == 'S' || Key == 's')//so this will never execute
10724  {
10725  SaveSessionButton->Click();
10726  }
10727  }
10728  }
10729  }
10730 
10731 //Timetable clock adjust panel
10732  if(Level1Mode == OperMode && TTClockAdjPanel->Enabled && TTClockAdjPanel->Visible && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
10733  { //use Shift.Contains(ssShift etc instead of ShiftKey as that not set if pressed second after Ctrl key pressed
10734  if(Shift.Contains(ssShift))
10735  {
10736  if(TTClockExitButton->Visible && TTClockExitButton->Enabled && (Key == 'A' || Key == 'a'))
10737  {
10738  TTClockExitButton->Click();
10739  }
10740  if(TTClockResetButton->Visible && TTClockResetButton->Enabled && (Key == 'R' || Key == 'r'))
10741  {
10742  TTClockResetButton->Click();
10743  }
10744  }
10745  }
10746 
10747 //Track build panel
10748  if((Level1Mode == TrackMode) && TrackBuildPanel->Visible && TrackBuildPanel->Enabled)
10749  {
10750  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
10751  {
10752  if(AddTrackButton->Visible && AddTrackButton->Enabled && (Key == 'A' || Key == 'a')) //add/remove track elements
10753  {
10754  AddTrackButton->Click();
10755  }
10756  if(SigAspectButton->Visible && SigAspectButton->Enabled && (Key == 'S' || Key == 's')) //cycle through signal aspects
10757  {
10758  SigAspectButton->Click();
10759  }
10760  if(TrackOKButton->Visible && TrackOKButton->Enabled && (Key == 'L' || Key == 'l')) //link track
10761  {
10762  TrackOKButton->Click();
10763  }
10764  if(FontButton->Visible && FontButton->Enabled && (Key == 'F' || Key == 'f')) //change font
10765  {
10766  FontButton->Click();
10767  }
10768  if(LocationNameButton->Visible && LocationNameButton->Enabled && (Key == 'N' || Key == 'n')) //name locations
10769  {
10770  LocationNameButton->Click();
10771  }
10772  if(SetLengthsButton->Visible && SetLengthsButton->Enabled && (Key == 'D' || Key == 'd')) //set distances/speeds
10773  {
10774  SetLengthsButton->Click();
10775  }
10776  if(AddTextButton->Visible && AddTextButton->Enabled && (Key == 'T' || Key == 't')) //add text
10777  {
10778  AddTextButton->Click();
10779  }
10780  if(ScreenGridButton->Visible && ScreenGridButton->Enabled && (Key == 'G' || Key == 'g')) //toggle grid
10781  {
10782  ScreenGridButton->Click();
10783  }
10784  if(MoveTextOrGraphicButton->Visible && MoveTextOrGraphicButton->Enabled && (Key == 'M' || Key == 'm')) //move text or graphic
10785  {
10786  MoveTextOrGraphicButton->Click();
10787  }
10788  if(UserGraphicButton->Visible && UserGraphicButton->Enabled && (Key == 'I' || Key == 'i')) //insert image
10789  {
10790  UserGraphicButton->Click();
10791  }
10792  if(SetGapsButton->Visible && SetGapsButton->Enabled && (Key == 'J' || Key == 'j')) //join gaps
10793  {
10794  SetGapsButton->Click();
10795  }
10796  }
10797  if(Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10798  {
10799  if(SaveRailwayTBPButton->Visible && SaveRailwayTBPButton->Enabled) //save railway in trackbuild mode
10800  {
10801  SaveMenuItem->ShortCut = 0; //It's normally 16467 (Ctrl S) & will be restored in FormKeyUp. Has to be reset or will grab the key combination
10802  if(Key == 'S' || Key == 's')//so this will never execute
10803  {
10804  SaveRailwayTBPButton->Click();
10805  }
10806  }
10807  }
10808  if(!Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10809  {
10810  if((ExitTrackButton->Visible && ExitTrackButton->Enabled) && Key == '\x1b') //escape key
10811  {
10812  ExitTrackButton->Click();
10813  }
10814  }
10815  }
10816 
10817 //PrefDir panel
10818  if(Level1Mode == PrefDirMode && PrefDirPanel->Visible && PrefDirPanel->Enabled && !Shift.Contains(ssAlt))
10819  {
10820  if(!Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10821  {
10822  if((ExitPrefDirButton->Visible && ExitPrefDirButton->Enabled) && Key == '\x1b') //escape key
10823  {
10824  ExitPrefDirButton->Click();
10825  }
10826  }
10827  if(!Shift.Contains(ssShift) && Shift.Contains(ssCtrl))
10828  {
10829  if(SaveRailwayPDPButton->Visible && SaveRailwayPDPButton->Enabled)
10830  {
10831  SaveMenuItem->ShortCut = 0; //It's normally 16467 (Ctrl S) & will be restored in FormKeyUp. Has to be reset or will grab the key combination
10832  if(Key == 'S' || Key == 's')//so this will never execute
10833  {
10834  SaveRailwayPDPButton->Click();
10835  }
10836  }
10837  }
10838  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10839  {
10840  if(AddPrefDirButton->Visible && AddPrefDirButton->Enabled && (Key == 'A' || Key == 'a')) //add pref dir
10841  {
10842  AddPrefDirButton->Click();
10843  }
10844  if(DeleteOnePrefDirButton->Visible && DeleteOnePrefDirButton->Enabled && (Key == 'D' || Key == 'd')) //delete one pref dir
10845  {
10846  DeleteOnePrefDirButton->Click();
10847  }
10848  if(DeleteAllPrefDirButton->Visible && DeleteAllPrefDirButton->Enabled && (Key == 'C' || Key == 'c')) //delete all pref dirs
10849  {
10850  DeleteAllPrefDirButton->Click();
10851  }
10852  }
10853  }
10854 //Note that save button in BaseMode is handled by Ctrl S from the File menu
10855 
10856 //Timetable panel
10857  if(Level1Mode == TimetableMode && TimetablePanel->Visible && TimetablePanel->Enabled && !Shift.Contains(ssAlt))
10858  {
10859  if(!Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10860  {
10861  if(ExitTTModeButton->Visible && ExitTTModeButton->Enabled && Key == '\x1b') //escape key
10862  {
10863  ExitTTModeButton->Click();
10864  }
10865  }
10866  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl)) //show/hide timetable edit panel
10867  {
10868  if(ShowHideTTButton->Visible && ShowHideTTButton->Enabled)
10869  {
10870  if(!TimetableEditPanel->Visible)
10871  {
10872  if(Key == 'S' || Key == 's')
10873  {
10874  ShowHideTTButton->Click();
10875  }
10876  }
10877  else if(Key == 'H' || Key == 'h')
10878  {
10879  ShowHideTTButton->Click();
10880  }
10881  }
10882  }
10883  }
10884 
10885 //Timetable edit panel
10886 //These just set flags. The corresponding 'Click()' function executes separately to the keypress because Windows stores the key until after any directly linked key code
10887 //is executed then selects the timetable entry that begins with the letter corresponding to the key. Without this separation the list box is left with the wrong entry
10888 //showing. See DevHistory.txt for the version after v2.4.3 for details.
10889  if(Level1Mode == TimetableMode && TimetableEditPanel->Visible && TimetableEditPanel->Enabled && !Shift.Contains(ssAlt))
10890  {
10891  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10892  {
10893  AllEntriesTTListBoxTopPosition = AllEntriesTTListBox->TopIndex; //store value here before the Windows key press function runs (it runs after any local code)
10894  if(PreviousTTEntryButton->Enabled && (Key == 'L' || Key == 'l'))
10895  {
10896  PreviousTTEntryKeyFlag = true;
10897  }
10898  if(NextTTEntryButton->Enabled && (Key == 'N' || Key == 'n'))
10899  {
10900  NextTTEntryKeyFlag = true;
10901  }
10902  if(MoveTTEntryUpButton->Enabled && (Key == 'U' || Key == 'u'))
10903  {
10904  MoveTTEntryUpKeyFlag = true;
10905  }
10906  if(MoveTTEntryDownButton->Enabled && (Key == 'D' || Key == 'd'))
10907  {
10908  MoveTTEntryDownKeyFlag = true;
10909  }
10910  if(CopyTTEntryButton->Enabled && (Key == 'C' || Key == 'c'))
10911  {
10912  CopyTTEntryKeyFlag = true;
10913  }
10914  if(CutTTEntryButton->Enabled && (Key == 'X' || Key == 'x'))
10915  {
10916  CutTTEntryKeyFlag = true;
10917  }
10918  if(PasteTTEntryButton->Enabled && (Key == 'P' || Key == 'p'))
10919  {
10920  PasteTTEntryKeyFlag = true;
10921  }
10922  if(DeleteTTEntryButton->Enabled && (Key == 'E' || Key == 'e'))
10923  {
10924  DeleteTTEntryKeyFlag = true;
10925  }
10926 /* if(SaveTTEntryButton->Enabled && (Key == 'E' || Key == 'e')) //can't have save while editing entry as adds the letter to the entry
10927  {
10928  SaveTTEntryKeyFlag = true;
10929  }
10930  if(CancelTTActionButton->Enabled && (Key == 'K' || Key == 'k')) //can't have cancel while editing entry as adds the letter to the entry
10931  {
10932  CancelTTActionKeyFlag = true;
10933  }
10934 */
10935  if(NewTTEntryButton->Enabled && (Key == 'I' || Key == 'i'))
10936  {
10937  NewTTEntryKeyFlag = true;
10938  }
10939  if(AZOrderButton->Enabled && (Key == 'Z' || Key == 'z'))
10940  {
10941  AZOrderKeyFlag = true;
10942  }
10943 /*
10944  if(AddMinsButton->Enabled && (Key == 'M' || Key == 'm')) //can't have key here as adds the letter to the entry
10945  {
10946  AddMinsKeyFlag = true;
10947  }
10948  if(SubMinsButton->Enabled && (Key == 'B' || Key == 'b')) //can't have key here as adds the letter to the entry
10949  {
10950  SubMinsKeyFlag = true;
10951  }
10952 */
10953  if(TTServiceSyntaxCheckButton->Enabled && (Key == 'Q' || Key == 'q'))
10954  {
10956  }
10957  if(ValidateTimetableButton->Enabled && (Key == 'V' || Key == 'v'))
10958  {
10959  ValidateTimetableKeyFlag = true;
10960  }
10961  if(SaveTTButton->Enabled && (Key == 'T' || Key == 't'))
10962  {
10963  SaveTTKeyFlag = true;
10964  }
10965  if(SaveTTAsButton->Enabled && (Key == 'A' || Key == 'a'))
10966  {
10967  SaveTTAsKeyFlag = true;
10968  }
10969  if(RestoreTTButton->Enabled && (Key == 'R' || Key == 'r'))
10970  {
10971  RestoreTTKeyFlag = true;
10972  }
10973  if(ExportTTButton->Enabled && (Key == 'O' || Key == 'o'))
10974  {
10975  ExportTTKeyFlag = true;
10976  }
10977  if(ConflictAnalysisButton->Enabled && (Key == 'F' || Key == 'f'))
10978  {
10979  ConflictAnalysisKeyFlag = true;
10980  }
10981  }
10982  }
10983 
10984 
10985 //Information menu
10986  if(FloatingInfoMenu->Enabled && !Shift.Contains(ssAlt) && Shift.Contains(ssCtrl) && Shift.Contains(ssShift))
10987  {
10988  if(Key == 'I' || Key == 'i') //toggle track info
10989  {
10990  TrackInfoOnOffMenuItem->Click();
10991  }
10992  else if(TrainInfoMenuItem->Enabled)
10993  {
10994  if(Key == 'S' || Key == 's') //toggle train status info
10995  {
10997  }
10998  else if(Key == 'T' || Key == 't') //toggle train timetable info
10999  {
11000  TrainTTInfoOnOffMenuItem->Click();
11001  }
11002 
11003  }
11004  }
11005 //end of 2.4.2 addition
11006 
11007  }
11008  catch(const Exception &e)
11009  {
11010  ErrorLog(167, e.Message);
11011  }
11012 }
11013 
11014 // ---------------------------------------------------------------------------
11015 
11016 void __fastcall TInterface::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11017 {
11018  if((Key != VK_SHIFT) && (Key != VK_CONTROL))
11019  LastNonCtrlOrShiftKeyDown = -1; //reset value to no key down
11020  CtrlKey = false;
11021  ShiftKey = false;
11022  SaveMenuItem->ShortCut = 16467; //restore Ctrl S for save menu in case set to 0 in FormKeyDown
11023 }
11024 
11025 // ---------------------------------------------------------------------------
11026 
11027 void __fastcall TInterface::OutputLog1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11028 {
11029  if((Button == mbRight) && Level2OperMode == Operating)
11030  {
11031  OutputLog1->Caption = "";
11032  }
11033 }
11034 
11035 // ---------------------------------------------------------------------------
11036 
11037 void __fastcall TInterface::OutputLog2MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11038 {
11039  if((Button == mbRight) && Level2OperMode == Operating)
11040  {
11041  OutputLog2->Caption = "";
11042  }
11043 }
11044 // ---------------------------------------------------------------------------
11045 
11046 void __fastcall TInterface::OutputLog3MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11047 {
11048  if((Button == mbRight) && Level2OperMode == Operating)
11049  {
11050  OutputLog3->Caption = "";
11051  }
11052 }
11053 
11054 // ---------------------------------------------------------------------------
11055 
11056 void __fastcall TInterface::OutputLog4MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11057 {
11058  if((Button == mbRight) && Level2OperMode == Operating)
11059  {
11060  OutputLog4->Caption = "";
11061  }
11062 }
11063 
11064 // ---------------------------------------------------------------------------
11065 
11066 void __fastcall TInterface::OutputLog5MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11067 {
11068  if((Button == mbRight) && Level2OperMode == Operating)
11069  {
11070  OutputLog5->Caption = "";
11071  }
11072 }
11073 // ---------------------------------------------------------------------------
11074 
11075 void __fastcall TInterface::OutputLog6MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11076 {
11077  if((Button == mbRight) && Level2OperMode == Operating)
11078  {
11079  OutputLog6->Caption = "";
11080  }
11081 }
11082 
11083 // ---------------------------------------------------------------------------
11084 
11085 void __fastcall TInterface::OutputLog7MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11086 {
11087  if((Button == mbRight) && Level2OperMode == Operating)
11088  {
11089  OutputLog7->Caption = "";
11090  }
11091 }
11092 
11093 // ---------------------------------------------------------------------------
11094 
11095 void __fastcall TInterface::OutputLog8MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11096 {
11097  if((Button == mbRight) && Level2OperMode == Operating)
11098  {
11099  OutputLog8->Caption = "";
11100  }
11101 }
11102 
11103 // ---------------------------------------------------------------------------
11104 
11105 void __fastcall TInterface::OutputLog9MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11106 {
11107  if((Button == mbRight) && Level2OperMode == Operating)
11108  {
11109  OutputLog9->Caption = "";
11110  }
11111 }
11112 
11113 // ---------------------------------------------------------------------------
11114 
11115 void __fastcall TInterface::OutputLog10MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11116 {
11117  if((Button == mbRight) && Level2OperMode == Operating)
11118  {
11119  OutputLog10->Caption = "";
11120  }
11121 }
11122 
11123 // ---------------------------------------------------------------------------
11124 
11125 void __fastcall TInterface::AboutMenuItemClick(TObject *Sender)
11126 {
11127  try
11128  {
11129  if((Level1Mode == OperMode) && (Level2OperMode != PreStart))
11130  // if PreStart leave as is [Modified at v1.2.0 - formerly just 'if((Level1Mode == OperMode)']
11131  {
11133  SetLevel2OperMode(3);
11134  MasterClock->Enabled = false;
11135  }
11136  AboutForm->ShowModal();
11137  }
11138  catch(const Exception &e)
11139  {
11140  ErrorLog(168, e.Message);
11141  }
11142 }
11143 
11144 // ---------------------------------------------------------------------------
11145 
11146 void __fastcall TInterface::OpenHelpMenuItemClick(TObject *Sender)
11147 {
11148  try
11149  {
11150  // Helpfile allocated during construction of Interface
11151  Application->HelpKeyword(u"Introduction"); // added at v2.0.0 for .chm help file
11152  }
11153  catch(const Exception &e)
11154  {
11155  ErrorLog(175, e.Message);
11156  }
11157 }
11158 
11159 // ---------------------------------------------------------------------------
11160 
11161 void __fastcall TInterface::RailwayWebSiteMenuItemClick(TObject *Sender)
11162 {
11163  const UnicodeString Link = "http://www.railwayoperationsimulator.com";
11164  ::ShellExecute(Handle, NULL, (Link).c_str(), NULL, NULL, SW_SHOWNORMAL);
11165 }
11166 
11167 // ---------------------------------------------------------------------------
11168 
11169 void __fastcall TInterface::BlackBgndMenuItemClick(TObject *Sender)
11170 {
11171  try
11172  {
11173  TrainController->LogEvent("BlackBgndMenuItemClick");
11174  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",BlackBgndMenuItemClick");
11175  TColor OldTransparentColour = Utilities->clTransparent;
11176  Utilities->clTransparent = TColor(0);
11177  SelectBitmap->TransparentColor = Utilities->clTransparent;
11180 
11181  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
11182  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
11183  Level1Mode = BaseMode;
11184  SetLevel1Mode(128);
11185  Utilities->CallLogPop(1797);
11186  }
11187  catch(const Exception &e)
11188  {
11189  ErrorLog(170, e.Message);
11190  }
11191 }
11192 
11193 // ---------------------------------------------------------------------------
11194 
11195 void __fastcall TInterface::WhiteBgndMenuItemClick(TObject *Sender)
11196 {
11197  try
11198  {
11199  TrainController->LogEvent("WhiteBgndMenuItemClick");
11200  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",WhiteBgndMenuItemClick");
11201  TColor OldTransparentColour = Utilities->clTransparent;
11202  Utilities->clTransparent = TColor(0xFFFFFF);
11203  SelectBitmap->TransparentColor = Utilities->clTransparent;
11206 
11207  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
11208  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
11209  Level1Mode = BaseMode;
11210  SetLevel1Mode(129);
11211  Utilities->CallLogPop(1798);
11212  }
11213  catch(const Exception &e)
11214  {
11215  ErrorLog(171, e.Message);
11216  }
11217 }
11218 
11219 // ---------------------------------------------------------------------------
11220 
11221 void __fastcall TInterface::BlueBgndMenuItemClick(TObject *Sender)
11222 {
11223  try
11224  {
11225  TrainController->LogEvent("BlueBgndMenuItemClick");
11226  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",BlueBgndMenuItemClick");
11227  TColor OldTransparentColour = Utilities->clTransparent;
11228  Utilities->clTransparent = TColor(0x330000);
11229  SelectBitmap->TransparentColor = Utilities->clTransparent;
11232 
11233  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
11234  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
11235  Level1Mode = BaseMode;
11236  SetLevel1Mode(130);
11237  Utilities->CallLogPop(1799);
11238  }
11239  catch(const Exception &e)
11240  {
11241  ErrorLog(172, e.Message);
11242  }
11243 }
11244 
11245 // ---------------------------------------------------------------------------
11246 
11247 void __fastcall TInterface::SpeedToggleButtonClick(TObject *Sender)
11248 {
11249  if(SpeedTopLabel->Caption == "mph")
11250  {
11251  SpeedTopLabel->Caption = "km/h";
11252  SpeedBottomLabel->Caption = "mph";
11253  }
11254  else
11255  {
11256  SpeedTopLabel->Caption = "mph";
11257  SpeedBottomLabel->Caption = "km/h";
11258  }
11259  // swap values to match toggle state
11260  UnicodeString SavedTopValue = SpeedEditBox->Text;
11261  UnicodeString SavedBottomValue = SpeedVariableLabel->Caption;
11262 
11263  SpeedEditBox->Text = SavedBottomValue;
11264  SpeedVariableLabel->Caption = SavedTopValue;
11265 }
11266 // ---------------------------------------------------------------------------
11267 
11268 void __fastcall TInterface::SpeedToggleButton2Click(TObject *Sender)
11269 {
11270  if(SpeedTopLabel2->Caption == "mph")
11271  {
11272  SpeedTopLabel2->Caption = "km/h";
11273  SpeedBottomLabel2->Caption = "mph";
11274  }
11275  else
11276  {
11277  SpeedTopLabel2->Caption = "mph";
11278  SpeedBottomLabel2->Caption = "km/h";
11279  }
11280  // swap values to match toggle state
11281  UnicodeString SavedTopValue = SpeedEditBox2->Text;
11282  UnicodeString SavedBottomValue = SpeedVariableLabel2->Caption;
11283 
11284  SpeedEditBox2->Text = SavedBottomValue;
11285  SpeedVariableLabel2->Caption = SavedTopValue;
11286 }
11287 // ---------------------------------------------------------------------------
11288 
11289 void __fastcall TInterface::SpeedEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11290 {
11291  try
11292  {
11293  TrainController->LogEvent("SpeedEditBoxKeyUp," + AnsiString(Key));
11294  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SpeedEditBoxKeyUp," + AnsiString(Key));
11295  bool ErrorFlag = false, TooBigFlag = false;
11296  if(SpeedEditBox->Text.Length() > 0)
11297  {
11298  if(SpeedEditBox->Text.Length() > 5)
11299  {
11300  TooBigFlag = true;
11301  }
11302  for(int x = 1; x <= SpeedEditBox->Text.Length(); x++)
11303  {
11304  if((SpeedEditBox->Text[x] < '0') || (SpeedEditBox->Text[x] > '9'))
11305  {
11306  SpeedVariableLabel->Caption = "Entry error";
11307  ErrorFlag = true;
11308  break;
11309  }
11310  if(TooBigFlag)
11311  {
11312  SpeedVariableLabel->Caption = "Too big";
11313  break;
11314  }
11315  }
11316  if(!ErrorFlag && !TooBigFlag)
11317  {
11318 /*
11319  1 mph = 1.609344 km/h
11320  1 km/h = 0.621371 mph
11321 */
11322  if(SpeedTopLabel->Caption == "mph")
11323  {
11324  // do mph-to-km/h conversion
11325  int MPH = SpeedEditBox->Text.ToInt();
11326  int KPH = (MPH * 1.609344) + 0.5;
11327  SpeedVariableLabel->Caption = UnicodeString(KPH);
11328  }
11329  else
11330  {
11331  // do km/h-to-mph conversion
11332  int KPH = SpeedEditBox->Text.ToInt();
11333  int MPH = (KPH * 0.621371) + 0.5;
11334  SpeedVariableLabel->Caption = UnicodeString(MPH);
11335  }
11336  }
11337  }
11338  else
11339  {
11340  SpeedVariableLabel->Caption = "";
11341  }
11342  Utilities->CallLogPop(1865);
11343  }
11344  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11345  {
11346  SpeedVariableLabel->Caption = "Entry error";
11347  }
11348  catch(const Exception &e)
11349  {
11350  ErrorLog(176, e.Message);
11351  }
11352 }
11353 
11354 // ---------------------------------------------------------------------------
11355 
11356 void __fastcall TInterface::PowerToggleButtonClick(TObject *Sender)
11357 {
11358  if(PowerTopLabel->Caption == "HP")
11359  {
11360  PowerTopLabel->Caption = "kW";
11361  PowerBottomLabel->Caption = "HP";
11362  }
11363  else
11364  {
11365  PowerTopLabel->Caption = "HP";
11366  PowerBottomLabel->Caption = "kW";
11367  }
11368  // swap values to match toggle state
11369  UnicodeString SavedTopValue = PowerEditBox->Text;
11370  UnicodeString SavedBottomValue = PowerVariableLabel->Caption;
11371 
11372  PowerEditBox->Text = SavedBottomValue;
11373  PowerVariableLabel->Caption = SavedTopValue;
11374 }
11375 // ---------------------------------------------------------------------------
11376 
11377 void __fastcall TInterface::PowerEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11378 {
11379  try
11380  {
11381  TrainController->LogEvent("PowerEditBoxKeyUp," + AnsiString(Key));
11382  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PowerEditBoxKeyUp," + AnsiString(Key));
11383  bool ErrorFlag = false, TooBigFlag = false;
11384  if(PowerEditBox->Text.Length() > 0)
11385  {
11386  if(PowerEditBox->Text.Length() > 8)
11387  {
11388  TooBigFlag = true;
11389  }
11390  for(int x = 1; x <= PowerEditBox->Text.Length(); x++)
11391  {
11392  if((PowerEditBox->Text[x] < '0') || (PowerEditBox->Text[x] > '9'))
11393  {
11394  PowerVariableLabel->Caption = "Entry error";
11395  ErrorFlag = true;
11396  break;
11397  }
11398  if(TooBigFlag)
11399  {
11400  PowerVariableLabel->Caption = "Too big";
11401  break;
11402  }
11403  }
11404  if(!ErrorFlag && !TooBigFlag)
11405  {
11406 /*
11407  1 kW = 1.340482574 HP
11408  1 HP = 0.745699872 kW
11409 */
11410  if(PowerTopLabel->Caption == "HP")
11411  {
11412  // do HP-to-kW conv
11413  int HP = PowerEditBox->Text.ToInt();
11414  int KW = (HP * 0.745699872) + 0.5;
11415  PowerVariableLabel->Caption = UnicodeString(KW);
11416  }
11417  else
11418  {
11419  // do kW-to-HP conv
11420  int KW = PowerEditBox->Text.ToInt();
11421  int HP = (KW * 1.340482574) + 0.5;
11422  PowerVariableLabel->Caption = UnicodeString(HP);
11423  }
11424  }
11425  }
11426  else
11427  {
11428  PowerVariableLabel->Caption = "";
11429  }
11430  Utilities->CallLogPop(1868);
11431  }
11432  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11433  {
11434  PowerVariableLabel->Caption = "Entry error";
11435  }
11436  catch(const Exception &e)
11437  {
11438  ErrorLog(179, e.Message);
11439  }
11440 }
11441 // ---------------------------------------------------------------------------
11442 
11443 void __fastcall TInterface::SpeedEditBox2KeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11444 {
11445  try
11446  {
11447  TrainController->LogEvent("SpeedEditBox2KeyUp," + AnsiString(Key));
11448  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SpeedEditBox2KeyUp," + AnsiString(Key));
11449  bool ErrorFlag = false, TooBigFlag = false;
11450  if(SpeedEditBox2->Text.Length() > 0)
11451  {
11452  if(SpeedEditBox2->Text.Length() > 5)
11453  {
11454  TooBigFlag = true;
11455  }
11456  for(int x = 1; x <= SpeedEditBox2->Text.Length(); x++)
11457  {
11458  if((SpeedEditBox2->Text[x] < '0') || (SpeedEditBox2->Text[x] > '9'))
11459  {
11460  SpeedVariableLabel2->Caption = "Entry error";
11461  ErrorFlag = true;
11462  break;
11463  }
11464  if(TooBigFlag)
11465  {
11466  SpeedVariableLabel2->Caption = "Too big";
11467  break;
11468  }
11469  }
11470  if(!ErrorFlag && !TooBigFlag)
11471  {
11472 /*
11473  1 mph = 1.609344 km/h
11474  1 km/h = 0.621371 mph
11475 */
11476  if(SpeedTopLabel2->Caption == "mph")
11477  {
11478  // do mph-to-km/h conversion
11479  int MPH = SpeedEditBox2->Text.ToInt();
11480  int KPH = (MPH * 1.609344) + 0.5;
11481  SpeedVariableLabel2->Caption = AnsiString(KPH);
11482  }
11483  else
11484  {
11485  // do km/h-to-mph conversion
11486  int KPH = SpeedEditBox2->Text.ToInt();
11487  int MPH = (KPH * 0.621371) + 0.5;
11488  SpeedVariableLabel2->Caption = AnsiString(MPH);
11489  }
11490  }
11491  }
11492  else
11493  {
11494  SpeedVariableLabel2->Caption = "";
11495  }
11496  Utilities->CallLogPop(1866);
11497  }
11498  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11499  {
11500  SpeedVariableLabel2->Caption = "Entry error";
11501  }
11502  catch(const Exception &e)
11503  {
11504  ErrorLog(177, e.Message);
11505  }
11506 }
11507 
11508 // ---------------------------------------------------------------------------
11509 
11510 void __fastcall TInterface::LengthEditKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11511 {
11512  try
11513  {
11514  TrainController->LogEvent("LengthEditKeyUp," + AnsiString(Key));
11515  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LengthEditKeyUp," + AnsiString(Key));
11516  bool ErrorFlag = false, TooLongFlag = false;
11517  if((MileEdit->Text.Length() > 0) && (MileEdit->Text.Length() < 6))
11518  {
11519  for(int x = 1; x <= MileEdit->Text.Length(); x++)
11520  {
11521  if((MileEdit->Text[x] < '0') || (MileEdit->Text[x] > '9'))
11522  {
11523  MetreVariableLabel->Caption = "Entry error";
11524  ErrorFlag = true;
11525  break;
11526  }
11527  }
11528  }
11529  if((ChainEdit->Text.Length() > 0) && (ChainEdit->Text.Length() < 6))
11530  {
11531  for(int x = 1; x <= ChainEdit->Text.Length(); x++)
11532  {
11533  if((ChainEdit->Text[x] < '0') || (ChainEdit->Text[x] > '9'))
11534  {
11535  MetreVariableLabel->Caption = "Entry error";
11536  ErrorFlag = true;
11537  break;
11538  }
11539  }
11540  }
11541  if((YardEdit->Text.Length() > 0) && (YardEdit->Text.Length() < 6))
11542  {
11543  for(int x = 1; x <= YardEdit->Text.Length(); x++)
11544  {
11545  if((YardEdit->Text[x] < '0') || (YardEdit->Text[x] > '9'))
11546  {
11547  MetreVariableLabel->Caption = "Entry error";
11548  ErrorFlag = true;
11549  break;
11550  }
11551  }
11552  }
11553  if((MileEdit->Text.Length() > 5) || (ChainEdit->Text.Length() > 5) || (YardEdit->Text.Length() > 5))
11554  {
11555  TooLongFlag = true;
11556  MetreVariableLabel->Caption = "Too big";
11557  }
11558  if(!ErrorFlag && !TooLongFlag)
11559  {
11560  int Miles = 0, Chains = 0, Yards = 0, Metres = 0;
11561  if(MileEdit->Text.Length() > 0)
11562  {
11563  Miles = MileEdit->Text.ToInt();
11564  }
11565  if(ChainEdit->Text.Length() > 0)
11566  {
11567  Chains = ChainEdit->Text.ToInt();
11568  }
11569  if(YardEdit->Text.Length() > 0)
11570  {
11571  Yards = YardEdit->Text.ToInt();
11572  }
11573  Metres = int((Miles * 1609.344) + (Chains * 20.1168) + (Yards * 0.9144) + 0.5);
11574  MetreVariableLabel->Caption = AnsiString(Metres);
11575  }
11576  if((MileEdit->Text.Length() == 0) && (ChainEdit->Text.Length() == 0) && (YardEdit->Text.Length() == 0))
11577  {
11578  MetreVariableLabel->Caption = "";
11579  }
11580  Utilities->CallLogPop(1867);
11581  }
11582  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11583  {
11584  MetreVariableLabel->Caption = "Entry error";
11585  }
11586  catch(const Exception &e)
11587  {
11588  ErrorLog(178, e.Message);
11589  }
11590 }
11591 
11592 // ---------------------------------------------------------------------------
11593 
11594 void __fastcall TInterface::TTClockAdjButtonClick(TObject *Sender)
11595 {
11596  try
11597  {
11598  TrainController->LogEvent("TTClockAdjButtonClick");
11599  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdjButtonClick");
11600 // Utilities->Clock2Stopped = true; // to keep panel buttons disabled, restarted on exit
11601  Display->HideWarningLog(0); //because this panel overwrites it
11602  TTClockAdjPanel->Visible = true;
11603  TTClockAdjButton->Enabled = false;
11604 /*
11605  OperatingPanelLabel->Caption = "Disabled"; all these now dealt with in ClockTimer2
11606  OperatingPanel->Enabled = false;
11607  ZoomButton->Enabled = false;
11608  HomeButton->Enabled = false;
11609  NewHomeButton->Enabled = false;
11610  ScreenLeftButton->Enabled = false;
11611  ScreenRightButton->Enabled = false;
11612  ScreenUpButton->Enabled = false;
11613  ScreenDownButton->Enabled = false;
11614 */
11615  Utilities->CallLogPop(1875);
11616  }
11617  catch(const Exception &e)
11618  {
11619  ErrorLog(181, e.Message);
11620  }
11621 }
11622 
11623 // ---------------------------------------------------------------------------
11624 
11625 void __fastcall TInterface::TTClockExitButtonClick(TObject *Sender)
11626 {
11627  try
11628  {
11629  TrainController->LogEvent("TTClockExitButtonClick");
11630  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockExitButtonClick");
11631  TTClockAdjPanel->Visible = false;
11632  TTClockAdjButton->Enabled = true;
11633 /* these dealt with in ClockTimer2
11634  ZoomButton->Enabled = true;
11635  HomeButton->Enabled = true;
11636  NewHomeButton->Enabled = true;
11637  ScreenLeftButton->Enabled = true;
11638  ScreenRightButton->Enabled = true;
11639  ScreenUpButton->Enabled = true;
11640  ScreenDownButton->Enabled = true;
11641  OperatingPanel->Enabled = true;
11642  OperatingPanelLabel->Caption = "Operation";
11643 */
11644  Display->ShowWarningLog(0);
11645  double TTClockTimeChange = double(TrainController->RestartTime) - PauseEntryRestartTime;
11646  if((TTClockSpeed != PauseEntryTTClockSpeed) || (TTClockTimeChange > 0.000347))
11647  // 30 seconds, min increase is 1 minute & don't trust doubles to stay exactly equal
11649  {
11650  TTClockAdjustWarningPanel->Top = MainScreen->Top + ((MainScreen->Height - TTClockAdjustWarningPanel->Height)/2);
11651  TTClockAdjustWarningPanel->Left = MainScreen->Left + ((MainScreen->Width - TTClockAdjustWarningPanel->Width)/2);
11652  TTClockAdjustWarningLabel->Caption =
11653  "Changes have been made to the timetable clock - you may wish to save a session before resuming operation.\n\nTo cancel all changes re-click the 'Adjust the timetable clock' button then click the reset button BEFORE resuming operation.";
11654  TTClockAdjustWarningPanel->Visible = true;
11655  }
11656 // Utilities->Clock2Stopped = false; // as above
11657  LastNonCtrlOrShiftKeyDown = -1; //to restore the ability to reselect T after adj panel hidden (FormKeyUp doesn't work because the Interface form doesn't have focus)
11658  Utilities->CallLogPop(1876);
11659  }
11660  catch(const Exception &e)
11661  {
11662  ErrorLog(182, e.Message);
11663  }
11664 }
11665 // ---------------------------------------------------------------------------
11666 
11667 void __fastcall TInterface::TTClockx2ButtonClick(TObject *Sender)
11668 {
11669  try
11670  {
11671  TrainController->LogEvent("TTClockx2ButtonClick");
11672  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx2ButtonClick");
11673  TTClockSpeed = 2;
11674  TTClockSpeedLabel->Caption = "x2";
11676  Utilities->CallLogPop(1878);
11677  }
11678  catch(const Exception &e)
11679  {
11680  ErrorLog(184, e.Message);
11681  }
11682 }
11683 
11684 // ---------------------------------------------------------------------------
11685 
11686 void __fastcall TInterface::TTClockx4ButtonClick(TObject *Sender)
11687 {
11688  try
11689  {
11690  TrainController->LogEvent("TTClockx4ButtonClick");
11691  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx4ButtonClick");
11692  TTClockSpeed = 4;
11693  TTClockSpeedLabel->Caption = "x4";
11695  Utilities->CallLogPop(1883);
11696  }
11697  catch(const Exception &e)
11698  {
11699  ErrorLog(189, e.Message);
11700  }
11701 }
11702 
11703 // ---------------------------------------------------------------------------
11704 
11705 void __fastcall TInterface::TTClockx8ButtonClick(TObject *Sender)
11706 {
11707  try
11708  {
11709  TrainController->LogEvent("TTClockx8ButtonClick");
11710  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx8ButtonClick");
11711  TTClockSpeed = 8;
11712  TTClockSpeedLabel->Caption = "x8";
11714  Utilities->CallLogPop(1884);
11715  }
11716  catch(const Exception &e)
11717  {
11718  ErrorLog(190, e.Message);
11719  }
11720 }
11721 
11722 // ---------------------------------------------------------------------------
11723 
11724 void __fastcall TInterface::TTClockx16ButtonClick(TObject *Sender)
11725 {
11726  try
11727  {
11728  TrainController->LogEvent("TTClockx16ButtonClick");
11729  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx16ButtonClick");
11730  TTClockSpeed = 16;
11731  TTClockSpeedLabel->Caption = "x16";
11733  Utilities->CallLogPop(1885);
11734  }
11735  catch(const Exception &e)
11736  {
11737  ErrorLog(191, e.Message);
11738  }
11739 }
11740 
11741 // ---------------------------------------------------------------------------
11742 
11743 void __fastcall TInterface::TTClockx1ButtonClick(TObject *Sender)
11744 {
11745  try
11746  {
11747  TrainController->LogEvent("TTClockx1ButtonClick");
11748  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx1ButtonClick");
11749  TTClockSpeed = 1;
11750  TTClockSpeedLabel->Caption = "x1";
11752  Utilities->CallLogPop(1886);
11753  }
11754  catch(const Exception &e)
11755  {
11756  ErrorLog(192, e.Message);
11757  }
11758 }
11759 
11760 // ---------------------------------------------------------------------------
11761 
11762 void __fastcall TInterface::TTClockxHalfButtonClick(TObject *Sender)
11763 {
11764  try
11765  {
11766  TrainController->LogEvent("TTClockxHalfButtonClick");
11767  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxHalfButtonClick");
11768  TTClockSpeed = 0.5;
11769  TTClockSpeedLabel->Caption = "x1/2";
11771  Utilities->CallLogPop(1887);
11772  }
11773  catch(const Exception &e)
11774  {
11775  ErrorLog(193, e.Message);
11776  }
11777 }
11778 
11779 // ---------------------------------------------------------------------------
11780 
11781 void __fastcall TInterface::TTClockxQuarterButtonClick(TObject *Sender)
11782 {
11783  try
11784  {
11785  TrainController->LogEvent("TTClockxQuarterButtonClick");
11786  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxQuarterButtonClick");
11787  TTClockSpeed = 0.25;
11788  TTClockSpeedLabel->Caption = "x1/4";
11790  Utilities->CallLogPop(1888);
11791  }
11792  catch(const Exception &e)
11793  {
11794  ErrorLog(194, e.Message);
11795  }
11796 }
11797 
11798 // ---------------------------------------------------------------------------
11799 
11800 void __fastcall TInterface::TTClockxEighthButtonClick(TObject *Sender)
11801 { // added for v2.3.0 for very big railways
11802  try
11803  {
11804  TrainController->LogEvent("TTClockxEighthButtonClick");
11805  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxEighthButtonClick");
11806  TTClockSpeed = 0.125;
11807  TTClockSpeedLabel->Caption = "x1/8";
11809  Utilities->CallLogPop(2099);
11810  }
11811  catch(const Exception &e)
11812  {
11813  ErrorLog(203, e.Message);
11814  }
11815 }
11816 // ---------------------------------------------------------------------------
11817 
11818 void __fastcall TInterface::TTClockxSixteenthButtonClick(TObject *Sender)
11819 { // added for v2.3.0 for very big railways
11820  try
11821  {
11822  TrainController->LogEvent("TTClockxSixteenthButtonClick");
11823  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxSixteenthButtonClick");
11824  TTClockSpeed = 0.0625;
11825  TTClockSpeedLabel->Caption = "x1/16";
11827  Utilities->CallLogPop(2100);
11828  }
11829  catch(const Exception &e)
11830  {
11831  ErrorLog(204, e.Message);
11832  }
11833 }
11834 
11835 // ---------------------------------------------------------------------------
11836 
11837 void __fastcall TInterface::TTClockAdd1hButtonClick(TObject *Sender)
11838 {
11839  try
11840  {
11841  TrainController->LogEvent("TTClockAdd1hButtonClick");
11842  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdd1hButtonClick");
11843  double TTClockIncrement = 1.0 / 24;
11844  TrainController->RestartTime += TDateTime(TTClockIncrement);
11847  Utilities->CallLogPop(1879);
11848  }
11849  catch(const Exception &e)
11850  {
11851  ErrorLog(185, e.Message);
11852  }
11853 }
11854 
11855 // ---------------------------------------------------------------------------
11856 
11857 void __fastcall TInterface::TTClockAdd10mButtonClick(TObject *Sender)
11858 {
11859  try
11860  {
11861  TrainController->LogEvent("TTClockAdd10mButtonClick");
11862  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdd10mButtonClick");
11863  double TTClockIncrement = 1.0 / 144;
11864  TrainController->RestartTime += TDateTime(TTClockIncrement);
11867  Utilities->CallLogPop(1881);
11868  }
11869  catch(const Exception &e)
11870  {
11871  ErrorLog(187, e.Message);
11872  }
11873 }
11874 
11875 // ---------------------------------------------------------------------------
11876 
11877 void __fastcall TInterface::TTClockAdd1mButtonClick(TObject *Sender)
11878 {
11879  try
11880  {
11881  TrainController->LogEvent("TTClockAdd1mButtonClick");
11882  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdd1mButtonClick");
11883  double TTClockIncrement = 1.0 / 1440;
11884  TrainController->RestartTime += TDateTime(TTClockIncrement);
11887  Utilities->CallLogPop(1882);
11888  }
11889  catch(const Exception &e)
11890  {
11891  ErrorLog(188, e.Message);
11892  }
11893 }
11894 
11895 // ---------------------------------------------------------------------------
11896 
11897 void __fastcall TInterface::TTClockResetButtonClick(TObject *Sender)
11898 {
11899  try
11900  {
11901  TrainController->LogEvent("TTClockResetButtonClick");
11902  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockResetButtonClick");
11907  if(TTClockSpeed == 2)
11908  TTClockSpeedLabel->Caption = "x2";
11909  else if(TTClockSpeed == 4)
11910  TTClockSpeedLabel->Caption = "x4";
11911  else if(TTClockSpeed == 8)
11912  TTClockSpeedLabel->Caption = "x8";
11913  else if(TTClockSpeed == 16)
11914  TTClockSpeedLabel->Caption = "x16";
11915  else if(TTClockSpeed == 0.5)
11916  TTClockSpeedLabel->Caption = "x1/2";
11917  else if(TTClockSpeed == 0.25)
11918  TTClockSpeedLabel->Caption = "x1/4";
11919  else if(TTClockSpeed == 0.125)
11920  TTClockSpeedLabel->Caption = "x1/8";
11921  else if(TTClockSpeed == 0.0625)
11922  TTClockSpeedLabel->Caption = "x1/16";
11923  else
11924  {
11925  TTClockSpeed = 1;
11926  TTClockSpeedLabel->Caption = "x1";
11927  }
11928  Utilities->CallLogPop(1880);
11929  }
11930  catch(const Exception &e)
11931  {
11932  ErrorLog(186, e.Message);
11933  }
11934 }
11935 
11936 // ---------------------------------------------------------------------------
11937 
11938 void __fastcall TInterface::PresetAutoSigRoutesButtonClick(TObject *Sender)
11939 {
11940  try
11941  {
11942  TrainController->LogEvent("PresetAutoSigRoutesButtonClick");
11943  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PresetAutoSigRoutesButtonClick");
11944  InfoPanel->Caption = "PRE-START: Presetting automatic signal routes";
11945  OperatingPanelLabel->Caption = "Disabled";
11946  OperatingPanel->Enabled = false; // becomes re-enabled during the call to ClockTimer2
11947  ZoomButton->Enabled = false;
11948  HomeButton->Enabled = false;
11949  NewHomeButton->Enabled = false;
11950  ScreenLeftButton->Enabled = false;
11951  ScreenRightButton->Enabled = false;
11952  ScreenUpButton->Enabled = false;
11953  ScreenDownButton->Enabled = false;
11954 
11955  Screen->Cursor = TCursor(-11); // Hourglass
11956  TPrefDirElement StartElement, EndElement;
11957  bool PointsChanged, AtLeastOneSet = false;
11958  int LastIteratorValue = 0;
11959  while(true)
11960  {
11961  if(!EveryPrefDir->GetStartAndEndPrefDirElements(0, StartElement, EndElement, LastIteratorValue))
11962  break;
11963  // rest of routine here - i.e. build the routes
11964  ConstructRoute->ClearRoute(); // in case not empty though should be
11965  AtLeastOneSet = true;
11966  if(ConstructRoute->GetPreferredRouteStartElement(1, StartElement.HLoc, StartElement.VLoc, EveryPrefDir, true, true))
11967  // true for both ConsecSignalsRoute & AutoSigsFlag
11968  {}
11969  if(ConstructRoute->GetNextPreferredRouteElement(1, EndElement.HLoc, EndElement.VLoc, EveryPrefDir, true, true, ConstructRoute->ReqPosRouteID,
11970  PointsChanged))
11971  {}
11973  }
11974  if(AtLeastOneSet)
11975  {
11978  }
11979  else
11980  {
11981  ShowMessage("No presettable automatic signal routes are available");
11982  }
11983  Screen->Cursor = TCursor(-2); // Arrow
11984  Utilities->CallLogPop(1994);
11985  }
11986  catch(const Exception &e)
11987  {
11988  ErrorLog(195, e.Message);
11989  }
11990 }
11991 
11992 // ---------------------------------------------------------------------------
11993 
11994 void __fastcall TInterface::FormResize(TObject *Sender) // new at v2.1.0
11995 {
11996  try
11997  {
11998  if(!SkipFormResizeEvent) // to avoid calling during startup and especially during shutdown
11999  { // else fails on shutdown because HiddenScreen & other things no longer exist
12000  int DispW = (Interface->Width - 64 - 16) / 16;
12001 // will truncate down to a multiple of 16 (64 = side panels and 16 compensates for excess width of Interface)
12002  int DispH = (Interface->Height - 192) / 16;
12003  MainScreen->Width = DispW * 16;
12004  MainScreen->Height = DispH * 16;
12005  Utilities->ScreenElementWidth = DispW;
12006  Utilities->ScreenElementHeight = DispH;
12007  HiddenScreen->Width = MainScreen->Width;
12008  HiddenScreen->Height = MainScreen->Height;
12009  PerformancePanel->Top = MainScreen->Top + MainScreen->Height - PerformancePanel->Height;
12010  PerformancePanel->Left = MainScreen->Left;
12011  OperatorActionPanel->Top = MainScreen->Top + MainScreen->Height - OperatorActionPanel->Height; // new at v2.2.0
12012  OperatorActionPanel->Left = MainScreen->Left + MainScreen->Width - OperatorActionPanel->Width;
12013  SigImagePanel->Left = (Interface->Width - SigImagePanel->Width) / 2; // added for v2.3.0
12014  DevelopmentPanel->Top = MainScreen->Top + MainScreen->Height - DevelopmentPanel->Height; // new v2.2.0
12015  DevelopmentPanel->Left = MainScreen->Left + MainScreen->Width - DevelopmentPanel->Width; // new v2.2.0
12016  MTBFEditBox->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 32; // new v2.4.0 32 is to place it above the positional panel
12017  MTBFLabel->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 30 - 55; // new v2.4.0 placed above and to the left of MTBFEditBox
12018  PositionalPanel->Left = MainScreen->Left + MainScreen->Width; // changed at v2.4.0
12019  PositionalPanel->Top = MainScreen->Top; // changed at v2.4.0
12020  PositionalPanel->Height = MainScreen->Height; // changed at v2.4.0
12021 
12022  if(!Display->ZoomOutFlag)
12023  {
12025  }
12026  else
12027  {
12028  Display->ClearDisplay(11);
12030  }
12031  Display->Update();
12032  }
12033  }
12034  catch(const Exception &e)
12035  {
12036  ErrorLog(197, e.Message);
12037  }
12038 }
12039 
12040 // ---------------------------------------------------------------------------
12041 
12042 void __fastcall TInterface::OperatorActionButtonClick(TObject *Sender)
12043 {
12044  try
12045  {
12046  TrainController->LogEvent("OperatorActionButtonClick");
12047  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperatorActionButtonClick");
12049  {
12050  ShowOperatorActionPanel = true;
12051  OperatorActionPanel->Visible = true;
12053  OperatorActionButton->Glyph->LoadFromResourceName(0, "HideOpActionPanel");
12054  }
12055  else
12056  {
12057  ShowOperatorActionPanel = false;
12058  OperatorActionPanel->Visible = false;
12060  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel");
12061  }
12062  Utilities->CallLogPop(2073);
12063  }
12064  catch(const Exception &e)
12065  {
12066  ErrorLog(199, e.Message);
12067  }
12068 }
12069 
12070 // ---------------------------------------------------------------------------
12071 
12073 {
12074  try
12075  {
12076  TrainController->LogEvent("ConverttoRightHandSignalsMenuItemClick");
12077  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ConverttoRightHandSignalsMenuItemClick");
12079  if(Utilities->RHSignalFlag) // RH sigs after conversion
12080  {
12081  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Left Hand Signals";
12083  {
12085  }
12086  else
12087  {
12089  }
12090  SigImagePanel->Caption = "Signals will be on the right hand side of the track";
12091  SigsOnLeftImage1->Visible = false;
12092  SigsOnLeftImage2->Visible = false;
12093  SigsOnRightImage1->Visible = true;
12094  SigsOnRightImage2->Visible = true;
12095  std::ofstream SigFile((CurDir + "\\Signal.hnd").c_str());
12096  if(SigFile.fail())
12097  {
12098  ShowMessage("Failed to store right hand signal setting, program will default to left hand signals when next loaded");
12099  }
12100  else
12101  {
12102  Utilities->SaveFileString(SigFile, "RHSignals");
12103  }
12104  }
12105  else // LH sigs after conversion
12106  {
12107  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Right Hand Signals";
12109  {
12111  }
12112  else
12113  {
12115  }
12116  SigImagePanel->Caption = "Signals will be on the left hand side of the track";
12117  SigsOnRightImage1->Visible = false;
12118  SigsOnRightImage2->Visible = false;
12119  SigsOnLeftImage1->Visible = true;
12120  SigsOnLeftImage2->Visible = true;
12121  std::ofstream SigFile((CurDir + "\\Signal.hnd").c_str());
12122  if(SigFile.fail())
12123  {
12124  // no need for message as will default to LH: ShowMessage("Failed to store left hand signal setting, program will default to left hand signals when next loaded");
12125  }
12126  else
12127  {
12128  Utilities->SaveFileString(SigFile, "LHSignals");
12129  }
12130  }
12131  Utilities->CallLogPop(2097);
12132  }
12133  catch(const Exception &e)
12134  {
12135  ErrorLog(202, e.Message);
12136  }
12137 }
12138 // ---------------------------------------------------------------------------
12139 
12140 void __fastcall TInterface::MTBFEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
12141 
12142 {
12143  try
12144  {
12145  TrainController->LogEvent("MTBFEditBoxKeyUp," + AnsiString(Key));
12146  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MTBFEditBoxKeyUp," + AnsiString(Key));
12147  if((Level1Mode != OperMode) || (Level2OperMode != PreStart))
12148  {
12149  Utilities->CallLogPop(2160);
12150  return;
12151  }
12152  bool TooBigFlag = false, BadCharsFlag = false;
12155  if(MTBFEditBox->Text.Length() > 0)
12156  {
12157  for(int x = 1; x <= MTBFEditBox->Text.Length(); x++)
12158  {
12159  if((MTBFEditBox->Text[x] < '0') || (MTBFEditBox->Text[x] > '9'))
12160  {
12161  BadCharsFlag = true;
12162  break;
12163  }
12164  }
12165  if(!BadCharsFlag)
12166  {
12167  if(StrToInt(MTBFEditBox->Text) > 10000)
12168  {
12169  TooBigFlag = true;
12170  }
12171  }
12172  if(TooBigFlag)
12173  {
12174  ShowMessage("Maximum value allowed is 10,000");
12175  MTBFEditBox->Text = "";
12178  Utilities->CallLogPop(2161);
12179  return;
12180  }
12181  if(BadCharsFlag)
12182  {
12183  ShowMessage("Value must be a whole number with no special characters");
12184  MTBFEditBox->Text = "";
12187  Utilities->CallLogPop(2162);
12188  return;
12189  }
12190  TrainController->AvHoursIntValue = StrToInt(MTBFEditBox->Text); // ok if user enters 0 as that means no failures
12192  }
12194  {
12195  MTBFEditBox->Text = "";
12197  }
12198  Utilities->CallLogPop(2163);
12199  }
12200  catch(const Exception &e)
12201  {
12202  ErrorLog(209, e.Message);
12203  }
12204 }
12205 
12206 // ---------------------------------------------------------------------------
12207 
12208 void __fastcall TInterface::MTBFEditBoxClick(TObject *Sender)
12209 {
12210  try
12211  {
12212  TrainController->LogEvent("MTBFEditBoxClick");
12213  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MTBFEditBoxClick");
12214  if((Level1Mode != OperMode) || (Level2OperMode != PreStart))
12215  {
12216  MTBFEditBox->ReadOnly = true; // it should be anyway but include here for safety
12218  "Values can only be entered or changed in Pre-Start mode\ni.e. after selecting 'Operate railway' but before clicking 'Run'");
12219  }
12220  Utilities->CallLogPop(2164);
12221  }
12222  catch(const Exception &e)
12223  {
12224  ErrorLog(210, e.Message);
12225  }
12226 }
12227 
12228 // ---------------------------------------------------------------------------
12229 
12230 void __fastcall TInterface::UserGraphicButtonClick(TObject *Sender)
12231 {
12232  try
12233  {
12234  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MTBFEditBoxClick");
12235  LengthConversionPanel->Visible = false;
12236  SpeedConversionPanel->Visible = false;
12237  DistanceKey->Visible = false;
12238  TrackElementPanel->Visible = false;
12239  SigAspectButton->Enabled = false;
12241  SetLevel2TrackMode(63);
12242  Display->Update();
12243  if((SelectedGraphicFileName != "") && (!Track->UserGraphicVector.empty())) //latter condition added at v2.6.0 because showed after ClearAll & reselect failed
12244  {
12245  UserGraphicReselectPanel->Visible = true;
12246  }
12247  else
12248  {
12249  UserGraphicReselectPanel->Visible = false;
12250  LoadUserGraphic(0);
12251  }
12252  Utilities->CallLogPop(2183);
12253  }
12254  catch(const Exception &e)
12255  {
12256  ErrorLog(212, e.Message);
12257  }
12258 }
12259 
12260 // ---------------------------------------------------------------------------
12261 
12262 void __fastcall TInterface::ReselectUserGraphicClick(TObject *Sender)
12263 {
12264  try
12265  {
12266  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ReselectUserGraphicClick");
12267  TrainController->LogEvent("ReselectUserGraphicClick " + SelectedGraphicFileName);
12268  UserGraphicReselectPanel->Visible = false;
12269  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.find(SelectedGraphicFileName);
12270  if(UGMIt == Track->UserGraphicMap.end())
12271  {
12272  ShowMessage("Unable to find graphic file " + SelectedGraphicFileName + ". Check it still exists.");
12273  Utilities->CallLogPop(2196);
12274  return;
12275  }
12277  SetLevel2TrackMode(64);
12278  Utilities->CallLogPop(2184);
12279  }
12280  catch(const Exception &e)
12281  {
12282  ErrorLog(213, e.Message);
12283  }
12284 }
12285 // ---------------------------------------------------------------------------
12286 
12287 void __fastcall TInterface::SelectNewGraphicClick(TObject *Sender)
12288 {
12289  try
12290  {
12291  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectNewGraphicClick");
12292  UserGraphicReselectPanel->Visible = false;
12293  LoadUserGraphic(1);
12294  Utilities->CallLogPop(2185);
12295  }
12296  catch(const Exception &e)
12297  {
12298  ErrorLog(214, e.Message);
12299  }
12300 }
12301 
12302 // ---------------------------------------------------------------------------
12303 
12304 void __fastcall TInterface::TTClockAdjustOKButtonClick(TObject *Sender)
12305 {
12306  try
12307  {
12308  TrainController->LogEvent("TTClockAdjustOKButtonClick");
12309  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdjustOKButtonClick");
12310  TTClockAdjustWarningPanel->Visible = false;
12311  if(TTClockAdjustCheckBox->Checked)
12312  {
12313  TTClockAdjustWarningHide = true;
12314  }
12315  Utilities->CallLogPop(2219);
12316  }
12317  catch(const Exception &e)
12318  {
12319  ErrorLog(216, e.Message);
12320  }
12321 }
12322 
12323 //---------------------------------------------------------------------------
12324 
12325 void __fastcall TInterface::ConflictAnalysisButtonClick(TObject *Sender)
12326 {
12327  try
12328  {
12329  TrainController->LogEvent("ConflictAnalysisButtonClick");
12330  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ConflictAnalysisButtonClick");
12331  ConflictPanel->Visible = true;
12332  Utilities->CallLogPop(2220);
12333  }
12334  catch(const Exception &e)
12335  {
12336  ErrorLog(217, e.Message);
12337  }
12338 }
12339 
12340 //---------------------------------------------------------------------------
12341 
12342 void __fastcall TInterface::CPCancelButtonClick(TObject *Sender)
12343 {
12344  try
12345  {
12346  TrainController->LogEvent("CPCancelButtonClick");
12347  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CPCancelButtonClick");
12348  ConflictPanel->Visible = false;
12349  Utilities->CallLogPop(2221);
12350  }
12351  catch(const Exception &e)
12352  {
12353  ErrorLog(218, e.Message);
12354  }
12355 }
12356 
12357 //---------------------------------------------------------------------------
12358 
12359 void __fastcall TInterface::CPGenFileButtonClick(TObject *Sender)
12360 {
12361  try
12362  {
12363  TrainController->LogEvent("CPGenFileButtonClick");
12364  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CPGenFileButtonClick");
12365  if(!CPArrivalsCheckBox->Checked && !CPDeparturesCheckBox->Checked && !CPAtLocCheckBox->Checked)
12366  {
12367  ShowMessage("No boxes ticked!");
12368  }
12369  else //keep ticks & range values from last time, only reset on startup
12370  {
12371  Screen->Cursor = TCursor(-11);//hourglass
12372  AnsiString TTTitle;
12374  {
12375  for(int x = CreateEditTTFileName.Length(); x > 0; x--) // first need to strip out the timetable title from the full name
12376  {
12377  if(CreateEditTTFileName[x] == '\\')
12378  {
12379  TTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
12380  break;
12381  }
12382  }
12384  CPAtLocCheckBox->Checked, CPEditArrRange->Text.ToInt(), CPEditDepRange->Text.ToInt()))
12385  {
12386  ShowMessage("Analysis complete and file created");
12387  }
12388  ConflictPanel->Visible = false;
12389  }
12390  }
12391  Screen->Cursor = TCursor(-2);//arrow
12392  Utilities->CallLogPop(2222);
12393  }
12394  catch(const Exception &e)
12395  {
12396  ErrorLog(219, e.Message);
12397  }
12398 }
12399 
12400 //---------------------------------------------------------------------------
12401 // end of fastcalls & directly associated functions
12402 // ---------------------------------------------------------------------------
12403 
12404 void TInterface::SetTopIndex(int Caller)
12405 {
12406 //Set TopIndex to the proper value & also Selected so don't have a different selection to the highlighted entry
12407  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetTopIndex");
12408  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < AllEntriesTTListBox->TopIndex)
12409  {
12411  }
12412  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (AllEntriesTTListBox->TopIndex + 45))
12413  {
12414  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
12415  }
12416  else
12417  {
12418  AllEntriesTTListBox->TopIndex = AllEntriesTTListBox->TopIndex;
12419  }
12420  AllEntriesTTListBox->Selected[TTCurrentEntryPtr - TimetableEditVector.begin()] = true;
12421  Utilities->CallLogPop(2207);
12422 }
12423 
12424 // ---------------------------------------------------------------------------
12425 
12426 void TInterface::ClearandRebuildRailway(int Caller) // now uses HiddenScreen to help avoid flicker
12427 {
12428  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ClearandRebuildRailway");
12429  bool ClockState = Utilities->Clock2Stopped;
12430 
12431  Utilities->Clock2Stopped = true;
12433  Track->RebuildUserGraphics(0, HiddenDisplay); // new at v2.4.0, plot first so all else overwrites, including the grid if selected
12434  if(ScreenGridFlag && (Level1Mode == TrackMode))
12435  {
12436  int WidthNum = int(MainScreen->Width / 160) + 1;
12437  int HeightNum = int(MainScreen->Height / 144) + 1;
12438  for(int x = 0; x < WidthNum; x++)
12439  {
12440  for(int y = 0; y < HeightNum; y++)
12441  {
12442  HiddenDisplay->PlotAbsolute(0, x * 160, y * 144, RailGraphics->GridBitmap);
12443  }
12444  }
12445  }
12446 
12447 // TextHandler->RebuildFromTextVector(1, HiddenDisplay); //This now incorporated in RebuildTrackAndText so that text is plotted after inactive
12448 // elements but before active elements. This is so text can overwite stations and non-station named locations.
12449 
12451 
12452 // Display->Output->Invalidate(); experiment, needs TDisplay Output to be public. Trying to invoke the white flashes that
12453 // used to occur frequently without Disp->Update() in PlotOriginal
12454 
12455  // OperMode LCs plotted below
12457  {
12459  }
12460 
12461  if(Level1Mode == PrefDirMode)
12462  {
12463  if(EveryPrefDir->PrefDirSize() > 0)
12464  {
12466  }
12468  {
12470  }
12471  }
12472 
12473  if(Level1Mode == TrackMode)
12474  {
12476  {
12477  LocationNameButton->Enabled = true;
12478  }
12479  else
12480  {
12481  LocationNameButton->Enabled = false;
12482  }
12483  }
12484 
12486  {
12488  DistanceKey->Visible = true;
12489  DistancesMarked = true;
12490  LengthConversionPanel->Visible = true;
12491  SpeedConversionPanel->Visible = true;
12492  }
12493 
12494  if(Level2TrackMode == DistanceContinuing) // for extended distances
12495  {
12496  if(ConstructPrefDir->PrefDirSize() > 0)
12497  {
12498  Track->LengthMarker(2, HiddenDisplay); //this line was after the next line until v2.5.1, changed so magenta not overrridden after PrefDirMarker called
12500  DistanceKey->Visible = true;
12501  DistancesMarked = true;
12502  LengthConversionPanel->Visible = true;
12503  SpeedConversionPanel->Visible = true;
12504  }
12505  }
12506 
12508  // this is to keep the distance markers if they are already present when Select is chosen, in case user wishes to choose SelectLengths,
12509  // don't need to display ConstructPrefDir marker as that only needed in DistanceContinuing mode
12510  {
12512  DistanceKey->Visible = true;
12513  }
12514 
12516  // cancel DistancesMarked if exit from any of these modes
12517  {
12518  DistancesMarked = false;
12519  DistanceKey->Visible = false;
12520  LengthConversionPanel->Visible = false; // added at v1.3.1 to remove when distance/speed setting exited
12521  SpeedConversionPanel->Visible = false; // added at v1.3.1 to remove when distance/speed setting exited
12522  }
12523 
12525  // in process of moving so use NewSelectBitmapHLoc & VLoc
12526  {
12528  }
12529 
12531  // not in process of moving or failed to click mouse within selection so use SelectBitmapHLoc & VLoc
12532  {
12534  }
12535 
12536  if(Level1Mode == OperMode)
12537  {
12539  if(!AllRoutes->LockedRouteVector.empty())
12540  {
12541  for(TAllRoutes::TLockedRouteVectorIterator LRVIT = AllRoutes->LockedRouteVector.end() - 1; LRVIT >= AllRoutes->LockedRouteVector.begin(); LRVIT--)
12542  {
12543  if(!(AllRoutes->TrackIsInARoute(7, LRVIT->LastTrackVectorPosition, LRVIT->LastXLinkPos)))
12544  {
12545  AllRoutes->LockedRouteVector.erase(LRVIT);
12546  // if end element not in route then a train must have entered it from the wrong end and erased the whole route,
12547  // hence no longer needed so get rid of it (end of route can't be points, crossover or bridge so danger of
12548  // route being on the other track of a 2-track element doesn't arise)
12549  continue;
12550  }
12551  TOneRoute Route = AllRoutes->GetFixedRouteAt(0, LRVIT->RouteNumber);
12552  int x = Route.PrefDirSize() - 1;
12553  bool BreakFlag = false;
12554  TPrefDirElement PrefDirElement = Route.GetFixedPrefDirElementAt(1, x);
12555  while(PrefDirElement.GetTrackVectorPosition() != LRVIT->TruncateTrackVectorPosition)
12556  {
12557  HiddenDisplay->PlotOutput(10, (PrefDirElement.HLoc) * 16, (PrefDirElement.VLoc) * 16,
12558  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
12559  if(!(AllRoutes->TrackIsInARoute(8, PrefDirElement.Conn[PrefDirElement.GetELinkPos()],
12560  PrefDirElement.ConnLinkPos[PrefDirElement.GetELinkPos()])))
12561  {
12562  BreakFlag = true;
12563  break; // train removed earlier element from route so stop here
12564  }
12565  x--;
12566  if(x < 0) //added after Albie Vowles reported error on 14/08/20 by email
12567  { //it means that part of the route (including that at the truncate point) has been cancelled, in this case by a train running past the signal
12568  BreakFlag = true; //at danger and cancelling the route elements in front of it. The locked route is now too short and this 'while' loop won't find
12569  break; //it, so x keeps decrementing and when it becomes -1 an error is thrown. This addition prevents the error.
12570  }
12571  PrefDirElement = Route.GetFixedPrefDirElementAt(2, x);
12572  }
12573  if(!BreakFlag)
12574  {
12575  if(PrefDirElement.GetTrackVectorPosition() == LRVIT->TruncateTrackVectorPosition)
12576  {
12577  HiddenDisplay->PlotOutput(11, (PrefDirElement.HLoc) * 16, (PrefDirElement.VLoc) * 16,
12578  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
12579  }
12580  }
12581  }
12582  }
12583 
12584  if(RouteMode == RouteContinuing)
12585  {
12587 // system thinks overlay is already plotted, so plot original to reset the OverlayPlotted flag
12590  if(AutoSigsFlag)
12592  else if(ConsecSignalsRoute)
12594  else
12596  }
12597 
12598  if(Track->PointFlashFlag)
12599  {
12600  // need to reset the screen location for picking up the original graphic
12601  int Left, Top; // Embarcadero change - these missing in error from Borland file
12603  // note that the above Pos values are wrt layout, not the screen, but the Left & Top values are wrt screen
12604  PointFlash->SetSourceRect(Left, Top);
12605  PointFlash->LoadOriginalScreenGraphic(4); // reload from new position
12606  // doesn't matter whether Flash was on or off when this function called as will sort itself out later (may miss a flash but won't be noticeable)
12607  }
12608 
12609  // now plot level crossings (must be after routes). These don't need any base elements to be plotted as they are already plotted.
12610  // In order to avoid plotting the whole LC for every element of a LC a bool value - LCPlotted - is used to save time
12611  for(unsigned int x = 0; x < Track->LCVector.size(); x++)
12612  {
12613  (Track->InactiveTrackVector.begin() + (*(Track->LCVector.begin() + x)))->LCPlotted = false;
12614  }
12615  for(unsigned int x = 0; x < Track->LCVector.size(); x++)
12616  {
12617  int BaseSpeedTag;
12618  TTrackElement ATE;
12619  TTrackElement ITE = *(Track->InactiveTrackVector.begin() + (*(Track->LCVector.begin() + x)));
12620  {
12621  BaseSpeedTag = Track->GetTrackElementFromTrackMap(0, ITE.HLoc, ITE.VLoc).SpeedTag;
12622  if(ITE.LCPlotted == false)
12623  {
12624  if(ITE.Attribute == 0)
12625  {
12627  }
12628  else if(ITE.Attribute == 1)
12629  {
12630  //need to determine if should plot green (manual) or red (auto), but all linked LCs have ConsecSignals set to 2 in BarriersDownVector if manual
12631  //so just need to test this for the HLoc & VLoc position match
12632  for(unsigned int x = 0; x < Track->BarriersDownVector.size(); x++)
12633  {
12634  if((Track->BarriersDownVector.at(x).HLoc == ITE.HLoc) && (Track->BarriersDownVector.at(x).VLoc == ITE.VLoc))
12635  {
12636  if(Track->BarriersDownVector.at(x).ConsecSignals == 2)
12637  {
12638  Track->PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers(0, BaseSpeedTag, ITE.HLoc, ITE.VLoc, HiddenDisplay, true); //true for manual = green
12639  }
12640  else
12641  {
12642  Track->PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers(1, BaseSpeedTag, ITE.HLoc, ITE.VLoc, HiddenDisplay, false); //false for auto = red
12643  }
12644  }
12645  }
12646  }
12647  // if ITE->Attribute == 2 then LC is changing, FlashingGraphics will take care of flashing & final plotting,
12648  // it won't set LCPlotted but no real time lost in this case
12649  }
12650  }}
12652  }
12653 
12654  Display->ZoomOutFlag = false;
12655  ZoomButton->Glyph->LoadFromResourceName(0, "ZoomOut");
12656  MainScreen->Picture->Bitmap->Assign(HiddenScreen->Picture->Bitmap);
12657  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
12658  Utilities->Clock2Stopped = ClockState;
12659  Utilities->CallLogPop(91);
12660 }
12661 
12662 // ---------------------------------------------------------------------------
12663 
12664 bool TInterface::HighLightOneGap(int Caller, int &HLoc, int &VLoc)
12665 {
12666  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",HighLightOneGap");
12667  if(Track->FindAndHighlightAnUnsetGap(1)) // true if find one
12668  {
12669  if(!PreventGapOffsetResetting) // don't reset display position if returning from zoomout mode
12670  {
12671  while((Display->DisplayOffsetH - Track->GetGapHLoc()) > 0)
12672  Display->DisplayOffsetH -= (Utilities->ScreenElementWidth / 2); // use 30 instead of 60 so less likely to appear behind the message box
12675  while((Display->DisplayOffsetV - Track->GetGapVLoc()) > 0)
12676  Display->DisplayOffsetV -= (Utilities->ScreenElementHeight / 2); // use 18 instead of 36 so less likely to appear behind the message box
12679  }
12680  InfoPanel->Visible = true;
12681  InfoPanel->Caption = "CONNECTING GAPS: Click on connecting element";
12682  ClearandRebuildRailway(31); // get rid of earlier gap selection
12683  Utilities->CallLogPop(92);
12684  return true; // return as one now identified & over to MainScreenMouseDown with Level2TrackMode = GapSetting
12685  }
12686  Utilities->CallLogPop(93);
12687  return false; // no unset ones left to find
12688 }
12689 
12690 // ---------------------------------------------------------------------------
12691 
12693 {
12694  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ClearEverything");
12695  if(FileChangedFlag)
12696  {
12697  UnicodeString MessageStr = "The railway has changed, close it without saving?";
12698  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
12699  if(button == IDNO)
12700  {
12701  Utilities->CallLogPop(1140);
12702  return false;
12703  }
12704  }
12705  Display->ClearDisplay(7);
12707 
12708  Display->DisplayOffsetH = 0;
12709  Display->DisplayOffsetV = 0;
12714 
12715 // these ensure that all persistent vectors, maps & multimaps etc are cleared
12716  delete TrainController;
12717  delete EveryPrefDir;
12718  delete ConstructRoute;
12719  delete ConstructPrefDir;
12720  delete AllRoutes;
12721  delete Track;
12722  delete TextHandler;
12723 // NB can't delete & recreate Utilities or will lose the CallLog file & have errors due to log being empty when try to
12724 // pop earlier pushed values
12725 // OK though as no containers in Utilities that need to clear & PerformanceFile recreated when begin to operate a later
12726 // railway
12727  TextHandler = new TTextHandler;
12728  Track = new TTrack;
12729  AllRoutes = new TAllRoutes;
12731  ConstructRoute = new TOneRoute;
12732  EveryPrefDir = new TOnePrefDir;
12734  PerformanceLogBox->Lines->Clear();
12735  ResetAll(1);
12736  Utilities->CallLogPop(94);
12737  return true;
12738 }
12739 
12740 // ---------------------------------------------------------------------------
12741 
12742 bool TInterface::FileIntegrityCheck(int Caller, char *FileName) const // true for success
12743 {
12744  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",FileIntegrityCheck," + AnsiString(FileName));
12745  std::ifstream VecFile(FileName);
12746 
12747  if(VecFile.is_open())
12748  {
12749  if(!Utilities->CheckFileStringZeroDelimiter(VecFile)) // Program version
12750  {
12751  VecFile.close();
12752  Utilities->CallLogPop(1805);
12753  return false;
12754  }
12755  if(!Utilities->CheckFileInt(VecFile, -1000000, 1000000)) // DisplayOffsetHHome
12756  {
12757  VecFile.close();
12758  Utilities->CallLogPop(1440);
12759  return false;
12760  }
12761  if(!Utilities->CheckFileInt(VecFile, -1000000, 1000000)) // DisplayOffsetVHome
12762  {
12763  VecFile.close();
12764  Utilities->CallLogPop(1441);
12765  return false;
12766  }
12767  bool GraphicsFollow = false;
12768  int NumberOfActiveElements;
12769  if(!(Track->CheckTrackElementsInFile(1, NumberOfActiveElements, GraphicsFollow, VecFile))) // for new loads
12770  {
12771  VecFile.close();
12772  Utilities->CallLogPop(95);
12773  return false;
12774  }
12775  if(!(TextHandler->CheckTextElementsInFile(0, VecFile)))
12776  {
12777  VecFile.close();
12778  Utilities->CallLogPop(96);
12779  return false;
12780  }
12781  if(!(EveryPrefDir->CheckOnePrefDir(0, NumberOfActiveElements, VecFile)))
12782  {
12783  VecFile.close();
12784  Utilities->CallLogPop(97);
12785  return false;
12786  }
12787  if(GraphicsFollow)
12788  {
12789  if(!Track->CheckUserGraphics(0, VecFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME)) // include path to Graphics folder
12790  {
12791  VecFile.close();
12792  Utilities->CallLogPop(2186);
12793  return false;
12794  }
12795  }
12796  VecFile.close();
12797  }
12798  else
12799  {
12800  Utilities->CallLogPop(1153);
12801  return false;
12802  }
12803  Utilities->CallLogPop(98);
12804  return true;
12805 }
12806 
12807 // ---------------------------------------------------------------------------
12808 
12809 void TInterface::Delay(int Caller, double Msec)
12810 {
12811  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",Delay," + AnsiString(Msec));
12812  TDateTime First, Second;
12813  bool Finished = false;
12814 
12815  First = TDateTime::CurrentDateTime();
12816  double TimeVal1 = 86400000 * double(First); // no of msec in a day
12817 
12818  while(!Finished)
12819  {
12820  Second = TDateTime::CurrentDateTime();
12821  double TimeVal2 = 86400000 * double(Second);
12822  if((TimeVal2 - TimeVal1) > Msec)
12823  Finished = true;
12824  }
12825  Utilities->CallLogPop(1203);
12826 }
12827 
12828 // ---------------------------------------------------------------------------
12829 
12831 {
12832  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ResetCurrentSpeedButton");
12833  if(CurrentSpeedButton)
12834  CurrentSpeedButton->Down = false;
12835  CurrentSpeedButton = 0;
12836  Utilities->CallLogPop(1204);
12837 }
12838 
12839 // ---------------------------------------------------------------------------
12840 
12842 {
12843  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",MovingTrainPresentOnFlashingRoute");
12844  int TrainID;
12845 
12846  if(ConstructRoute->SearchVectorSize() == 0)
12847  {
12848  Utilities->CallLogPop(99);
12849  return false;
12850  }
12851  for(unsigned int x = 0; x < ConstructRoute->SearchVectorSize(); x++)
12852  {
12853  TPrefDirElement PrefDirElement = ConstructRoute->GetFixedSearchElementAt(14, x);
12854  if(PrefDirElement.TrackType == Bridge)
12855  {
12856  if(PrefDirElement.GetXLinkPos() < 2)
12857  TrainID = Track->TrackElementAt(486, PrefDirElement.GetTrackVectorPosition()).TrainIDOnBridgeTrackPos01;
12858  else
12859  TrainID = Track->TrackElementAt(487, PrefDirElement.GetTrackVectorPosition()).TrainIDOnBridgeTrackPos23;
12860  }
12861  else
12862  TrainID = Track->TrackElementAt(488, PrefDirElement.GetTrackVectorPosition()).TrainIDOnElement;
12863  if((TrainID > -1) && !(TrainController->TrainVectorAtIdent(4, TrainID).Stopped()))
12864  {
12865  Utilities->CallLogPop(100);
12866  return true;
12867  }
12868  // check for crossed diagonal fouling by train added at v1.2.0
12869  int TrainID; // not used
12870  int LinkNumber1 = PrefDirElement.Link[PrefDirElement.GetELinkPos()];
12871  int LinkNumber2 = PrefDirElement.Link[PrefDirElement.GetXLinkPos()];
12872  if((LinkNumber1 == 1) || (LinkNumber1 == 3) || (LinkNumber1 == 7) || (LinkNumber1 == 9))
12873  {
12874  if(Track->DiagonalFouledByTrain(1, PrefDirElement.HLoc, PrefDirElement.VLoc, LinkNumber1, TrainID))
12875  {
12876  Utilities->CallLogPop(2037);
12877  return true;
12878  }
12879  }
12880  if((LinkNumber2 == 1) || (LinkNumber2 == 3) || (LinkNumber2 == 7) || (LinkNumber2 == 9))
12881  {
12882  if(Track->DiagonalFouledByTrain(2, PrefDirElement.HLoc, PrefDirElement.VLoc, LinkNumber2, TrainID))
12883  {
12884  Utilities->CallLogPop(2038);
12885  return true;
12886  }
12887  }
12888  }
12889  Utilities->CallLogPop(101);
12890  return false;
12891 }
12892 
12893 // ---------------------------------------------------------------------------
12894 
12896 {
12897  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",RevertToOriginalRouteSelector");
12898  AutoRouteStartMarker->PlotOriginal(26, Display); // if overlay not plotted will ignore
12899  SigRouteStartMarker->PlotOriginal(27, Display); // if overlay not plotted will ignore
12900  NonSigRouteStartMarker->PlotOriginal(28, Display); // if overlay not plotted will ignore
12901  RouteCancelFlag = false;
12903  {
12904  RouteCancelButton->Enabled = true;
12905  }
12906  else
12907  {
12908  RouteCancelButton->Enabled = false;
12909  }
12912 // reset here so that a n element that has been selected and then not doesn't remain set as a single element
12913  InfoPanel->Visible = true;
12914  if(Level2OperMode != Paused)
12915  {
12916  InfoPanel->Caption = InfoCaptionStore;
12917  }
12918  Utilities->CallLogPop(102);
12919 }
12920 
12921 // ---------------------------------------------------------------------------
12922 
12923 // usermode functions below
12925 {
12926  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel1Mode");
12927  if(!Display->ZoomOutFlag)
12928  {
12931  Track->GapFlashFlag = false;
12932  }
12933 // GapFlash resets when any mode selected unless zoomed out
12934 // note that if selecting zoom back in then this will be called before ZoomOutFlag is reset so won't
12935 // reset GapFlashFlag
12936  switch(Level1Mode) // use the data member
12937  {
12938  case BaseMode:
12939  CopyMenuItem->ShortCut = TextToShortCut(""); // added these for v2.1.0 to set default values after use of the 'Edit' menu during track building
12940  CutMenuItem->ShortCut = TextToShortCut(""); // to allow normal cutting/copying/pasting, especially in timetable construction or editing
12941  PasteMenuItem->ShortCut = TextToShortCut("");
12946  LengthConversionPanel->Visible = false;
12947  SpeedConversionPanel->Visible = false;
12948  TimetableEditPanel->Visible = false;
12949  TrainController->TTEditPanelVisible = false; //added at v2.6.0 for two location message
12950  TrackBuildPanel->Visible = false;
12951  TrackElementPanel->Visible = false;
12952  LocationNameTextBox->Visible = false;
12953  TextBox->Visible = false;
12954  TrackLengthPanel->Visible = false;
12955  InfoPanel->Visible = false;
12956  PrefDirPanel->Visible = false;
12957  TimetablePanel->Visible = false;
12958  OperatingPanel->Visible = false;
12959  PrefDirKey->Visible = false;
12960  TrackLinkedImage->Visible = false;
12961  TrackNotLinkedImage->Visible = false;
12962  GapsSetImage->Visible = false;
12963  GapsNotSetImage->Visible = false;
12964  LocationNamesSetImage->Visible = false;
12965  LocationNamesNotSetImage->Visible = false;
12966  ModeMenu->Enabled = true;
12967  FileMenu->Enabled = true;
12968  EditMenu->Enabled = false;
12969  BuildTrackMenuItem->Enabled = true;
12970  SigAspectButton->Enabled = false;
12971  Track->ChangingLCVector.clear();
12972  Track->BarriersDownVector.clear();
12974  ConverttoRightHandSignalsMenuItem->Enabled = false; // new at v2.3.0
12975  SigImagePanel->Visible = false; // new at v2.3.0
12976  MTBFEditBox->Visible = false; // new at v2.4.0
12977  MTBFLabel->Visible = false;
12978  TTClockAdjustWarningPanel->Visible = false;
12979  if(Track->IsTrackFinished())
12980  {
12981  PlanPrefDirsMenuItem->Enabled = true;
12982  if(TimetableTitle != "")
12983  {
12984  OperateRailwayMenuItem->Enabled = true;
12985  }
12986  else
12987  {
12988  OperateRailwayMenuItem->Enabled = false;
12989  }
12990  }
12991  else
12992  {
12993  PlanPrefDirsMenuItem->Enabled = false;
12994  OperateRailwayMenuItem->Enabled = false;
12995  }
12996  if(RlyFile)
12997  {
12998  LoadTimetableMenuItem->Enabled = true;
12999  }
13000  else
13001  {
13002  LoadTimetableMenuItem->Enabled = false;
13003  }
13004  LoadRailwayMenuItem->Enabled = true;
13005  if(NoRailway())
13006  {
13007  SaveAsMenuItem->Enabled = false;
13008  ImageMenu->Enabled = false;
13009  SaveImageAndGridMenuItem->Enabled = false;
13010  SaveImageNoGridMenuItem->Enabled = false;
13011  SaveImageAndPrefDirsMenuItem->Enabled = false;
13012  SaveOperatingImageMenuItem->Enabled = false;
13013  BlackBgndMenuItem->Enabled = false;
13014  WhiteBgndMenuItem->Enabled = false;
13015  BlueBgndMenuItem->Enabled = false;
13016  ConverttoRightHandSignalsMenuItem->Enabled = true; // new at v2.3.0
13017  SigImagePanel->Visible = true; // new at v2.3.0
13018  if(Utilities->clTransparent != TColor(0))
13019  {
13020  BlackBgndMenuItem->Enabled = true;
13021  }
13022  if(Utilities->clTransparent != TColor(0xFFFFFF))
13023  {
13024  WhiteBgndMenuItem->Enabled = true;
13025  }
13026  if(Utilities->clTransparent != TColor(0x330000))
13027  {
13028  BlueBgndMenuItem->Enabled = true;
13029  }
13030  ClearAllMenuItem->Enabled = false;
13031  InfoPanel->Visible = true;
13032  InfoPanel->Caption = "Select an option from the File, Mode or Help menus";
13033  }
13034  else
13035  {
13036  InfoPanel->Visible = false;
13037  SaveAsMenuItem->Enabled = true;
13038  ImageMenu->Enabled = true;
13039  SaveImageAndGridMenuItem->Enabled = true;
13040  SaveImageNoGridMenuItem->Enabled = true;
13041  if(EveryPrefDir->PrefDirSize() > 0)
13042  SaveImageAndPrefDirsMenuItem->Enabled = true;
13043  else
13044  SaveImageAndPrefDirsMenuItem->Enabled = false;
13045  BlackBgndMenuItem->Enabled = false;
13046  WhiteBgndMenuItem->Enabled = false;
13047  BlueBgndMenuItem->Enabled = false;
13048  SaveOperatingImageMenuItem->Enabled = false;
13049  ClearAllMenuItem->Enabled = true;
13050  }
13051  if(SavedFileName == "")
13052  {
13053  SaveMenuItem->Enabled = false;
13054  }
13055  else if(!FileChangedFlag)
13056  {
13057  SaveMenuItem->Enabled = false;
13058  }
13059  else if((SavedFileName[SavedFileName.Length()] == 'y') || (SavedFileName[SavedFileName.Length()] == 'Y')) // 'rly' file
13060  {
13061  if(!(Track->IsReadyForOperation()))
13062  {
13063  SaveMenuItem->Enabled = false; // can't save under its old name as not now a .rly file
13064  }
13065  else
13066  {
13067  SaveMenuItem->Enabled = true; // must have changed some of the PrefDirs (because FileChangedFlag is true)
13068  }
13069  }
13070  else
13071  {
13072  SaveMenuItem->Enabled = true;
13073  }
13074  LoadSessionMenuItem->Enabled = true;
13075  ExitMenuItem->Enabled = true;
13076  ScreenGridFlag = false;
13077  TrainController->CrashWarning = false;
13078  TrainController->DerailWarning = false;
13079  TrainController->SPADWarning = false;
13081  TrainController->CallOnWarning = false;
13084  UserGraphicReselectPanel->Visible = false;
13085  ClearandRebuildRailway(32); // to get rid of unwanted displays (eg distance markers)
13086  SetTrackBuildImages(13);
13087  break;
13088 
13089  case TimetableMode:
13093  ModeMenu->Enabled = false;
13094  SigImagePanel->Visible = false; // new at v2.3.0
13095  FileMenu->Enabled = false;
13096  EditMenu->Enabled = false;
13097  FloatingInfoMenu->Enabled = false;
13098  ImageMenu->Enabled = false;
13099  TimetableEditPanel->BringToFront();
13100  TimetableHandler();
13101  break;
13102 
13103  case TrackMode:
13104  if(Level2TrackMode == CutMoving)
13105  {
13106  Level2TrackMode = Pasting; // paste the selection
13107  SetLevel2TrackMode(52);
13108  }
13113  TrackBuildPanel->Visible = true;
13114  TrackBuildPanelLabel->Caption = "Build/modify";
13115  TrackElementPanel->Visible = false;
13116  TrackLengthPanel->Visible = false;
13117  PrefDirPanel->Visible = false;
13118  TimetablePanel->Visible = false;
13119  OperatingPanel->Visible = false;
13120  InfoPanel->Visible = false;
13121  InfoPanel->Caption = "";
13122  LocationNameTextBox->Visible = false;
13123  TextBox->Visible = false;
13124  ModeMenu->Enabled = false;
13125  SigImagePanel->Visible = false; // new at v2.3.0
13126  FileMenu->Enabled = false;
13127  // set edit menu items
13129  // track buttons
13130  AddTrackButton->Enabled = true;
13132  {
13133  LocationNameButton->Enabled = true;
13134  }
13135  else
13136  {
13137  LocationNameButton->Enabled = false;
13138  }
13139  ScreenGridButton->Enabled = true;
13140  ExitTrackButton->Enabled = true;
13141  SetGapsButton->Enabled = false;
13142  TrackOKButton->Enabled = false;
13143  if(Track->GapsUnset(5))
13144  {
13145  SetGapsButton->Enabled = true;
13146  }
13147  // only enable if there are gaps still to be set (returns false for no track)
13148  else
13149  {
13150  if(!(Track->NoActiveTrack(2)) && !(Track->IsTrackFinished()))
13151  {
13152  TrackOKButton->Enabled = true;
13153  }
13154  // TrackOK only enabled if track exists, there are no unset gaps, and track not finished
13155  }
13156  SetLengthsButton->Enabled = false;
13157  if(Track->IsTrackFinished()) // can only set lengths for several elements together if TrackFinished
13158  {
13159  SetLengthsButton->Enabled = true;
13160  }
13161  // text buttons
13162  AddTextButton->Enabled = true;
13163  TextOrUserGraphicGridButton->Enabled = true;
13164  FontButton->Enabled = true;
13165  MoveTextOrGraphicButton->Enabled = false;
13166  if(TextHandler->TextVectorSize(9) > 0)
13167  {
13168  MoveTextOrGraphicButton->Enabled = true;
13169  }
13170  if(!Track->UserGraphicVector.empty())
13171  {
13172  MoveTextOrGraphicButton->Enabled = true;
13173  }
13174  SelectionValid = false;
13176  TimetableTitle = "";
13177  SetCaption(0);
13178  break;
13179 
13180  case PrefDirMode:
13184  PrefDirPanel->Visible = true;
13185  PrefDirPanelLabel->Caption = "Preferred direction selection";
13186 
13187  InfoPanel->Visible = true;
13188  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Select preferred direction start location (right click to erase)";
13189  PrefDirKey->Visible = true;
13190  ModeMenu->Enabled = false;
13191  SigImagePanel->Visible = false; // new at v2.3.0
13192  FileMenu->Enabled = false;
13193 // set edit menu items
13195  AddPrefDirButton->Enabled = false;
13196  DeleteOnePrefDirButton->Enabled = false;
13198  if(EveryPrefDir->PrefDirSize() > 0)
13199  {
13200  DeleteAllPrefDirButton->Visible = true;
13201  DeleteAllPrefDirButton->Enabled = true;
13202  SaveImageAndPrefDirsMenuItem->Enabled = true;
13203  }
13204  else
13205  {
13206  DeleteAllPrefDirButton->Enabled = false;
13207  SaveImageAndPrefDirsMenuItem->Enabled = false;
13208  }
13209  ExitPrefDirButton->Enabled = true;
13210  ClearandRebuildRailway(33); // to mark PrefDirs & clear earlier PrefDir markers
13211 // TimetableTitle = ""; no need to unload timetable if only PrefDirs being changed
13212 // SetCaption();
13213  break;
13214 
13215  case OperMode: // if there are any PrefDirs, set to SigPref, else to NoSigNonPref; start in Paused mode
13219  OperatingPanel->Visible = true;
13220  OperatingPanelLabel->Caption = "Operation";
13221 
13222  CallingOnButton->Visible = false;
13223  PresetAutoSigRoutesButton->Visible = true;
13224  PresetAutoSigRoutesButton->Enabled = true;
13225  InfoPanel->Visible = true;
13226  SigImagePanel->Visible = false; // new at v2.3.0
13227  ModeMenu->Enabled = false;
13228  FileMenu->Enabled = false;
13229  EditMenu->Enabled = false;
13230  ImageMenu->Enabled = true;
13231  SaveImageAndGridMenuItem->Enabled = true;
13232  SaveImageNoGridMenuItem->Enabled = true;
13233  if(EveryPrefDir->PrefDirSize() > 0)
13234  SaveImageAndPrefDirsMenuItem->Enabled = true;
13235  else
13236  SaveImageAndPrefDirsMenuItem->Enabled = false;
13237  SaveOperatingImageMenuItem->Enabled = true;
13238  AutoSigsFlag = false;
13239  MTBFEditBox->Visible = true; // visible at pre-start whether any value set or not, so can set a value if required
13241  {
13242  MTBFEditBox->Text = AnsiString(TrainController->AvHoursIntValue);
13243  }
13244  else
13245  {
13246  MTBFEditBox->Text = "";
13247  }
13248  MTBFEditBox->ReadOnly = false; // because this is prestart mode
13249  MTBFLabel->Visible = true;
13250  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
13252  if(EveryPrefDir->PrefDirSize() > 0)
13253  {
13254  ConsecSignalsRoute = true;
13255  PreferredRoute = true;
13256  }
13257  else // no PrefDirs
13258  {
13259  ConsecSignalsRoute = false;
13260  PreferredRoute = false;
13261  }
13262 
13263  OperateButton->Enabled = true;
13264  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
13265  ExitOperationButton->Enabled = true;
13266  TTClockAdjButton->Enabled = true;
13267  ShowPerformancePanel = false;
13268  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
13269  ShowOperatorActionPanel = false; // new at v2.2.0
13270  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel"); // new v2.2.0
13271 
13273 
13274  Utilities->Clock2Stopped = false;
13278  TTClockSpeed = 1;
13279  TTClockSpeedLabel->Caption = "x1";
13282 
13283  PerformanceFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
13284  // format "16/06/2009 20:55:17"
13285  // avoid characters in filename:= / \ : * ? " < > |
13286  PerformanceFileName = CurDir + "\\" + PERFLOG_DIR_NAME + "\\Log " + PerformanceFileName + "; " + RailwayTitle + "; " + TimetableTitle + ".txt";
13287 
13288  Utilities->PerformanceFile.open(PerformanceFileName.c_str(), std::ios_base::out);
13289  if(Utilities->PerformanceFile.fail())
13290  {
13291  ShowMessage("Performance logfile failed to open, logs won't be saved. Ensure that there is a folder named " + PERFLOG_DIR_NAME +
13292  " in the folder where the 'Railway.exe' program file resides");
13293  }
13295 // DisableRouteButtons(2); enable route setting or pre-start
13296 // DisablePanelsStoreMainMenuStates();
13297  TrainController->ContinuationAutoSigVector.clear(); // for restarting after earlier run
13298  AllRoutes->LockedRouteVector.clear(); // for restarting after earlier run
13299 // TrainController->Operate(1);//plot trains that are present at TT start time, ready for running - no, allow route plotting prior to train entries
13300 
13301 // reset all performance indicators
13325 
13326  TrainController->OpActionPanelHintDelayCounter = 0; // new at v2.2.0 to reset hint delay
13327  OAListBox->Clear();
13328  OAListBox->Items->Add(L""); // hints for OpActionPanel
13329  OAListBox->Items->Add(L"");
13330  OAListBox->Items->Add(L"");
13331  OAListBox->Items->Add(L"Left click");
13332  OAListBox->Items->Add(L"headcode");
13333  OAListBox->Items->Add(L"to locate train");
13334  OAListBox->Items->Add(L"");
13335  OAListBox->Items->Add(L"");
13336  OAListBox->Items->Add(L"");
13337  OAListBox->Items->Add(L"");
13338  OAListBox->Items->Add(L"Left click and");
13339  OAListBox->Items->Add(L"hold grey area");
13340  OAListBox->Items->Add(L"to move panel");
13341 
13342  ClearandRebuildRailway(55); // so points display with one fillet
13343  break;
13344 
13345  case RestartSessionOperMode: // restart in Paused mode after a session load, sets both Level1Mode & Level2OperMode
13346  Level1Mode = OperMode;
13347 // Level2OperMode = Paused; this is now loaded during LoadInterface & could be PreStart of Paused
13350  OperatingPanel->Visible = true;
13351  OperatingPanelLabel->Caption = "Operation";
13352 
13353  CallingOnButton->Visible = true;
13354  PresetAutoSigRoutesButton->Visible = false;
13355  InfoPanel->Visible = true;
13356  ModeMenu->Enabled = false;
13357  SigImagePanel->Visible = false; // new at v2.3.0
13358  FileMenu->Enabled = false;
13359  EditMenu->Enabled = false;
13360  ImageMenu->Enabled = true;
13361  SaveImageAndGridMenuItem->Enabled = true;
13362  SaveImageNoGridMenuItem->Enabled = true;
13363  if(EveryPrefDir->PrefDirSize() > 0)
13364  SaveImageAndPrefDirsMenuItem->Enabled = true;
13365  else
13366  SaveImageAndPrefDirsMenuItem->Enabled = false;
13367  SaveOperatingImageMenuItem->Enabled = true;
13368 
13369  OperateButton->Enabled = true;
13370  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
13371  ExitOperationButton->Enabled = true;
13372  TTClockAdjButton->Enabled = true;
13375  if(Level2OperMode == Paused)
13376  DisableRouteButtons(3); // could be PreStart or Paused
13381  TTClockSpeed = 1;
13382  TTClockSpeedLabel->Caption = "x1";
13384  ShowPerformancePanel = false; // added at v2.2.0
13385  ShowOperatorActionPanel = false; // new at v2.2.0
13386  TrainController->OpActionPanelHintDelayCounter = 0; // new at v2.2.0 to reset hint delay
13387  OAListBox->Clear();
13388  OAListBox->Items->Add(L""); // hints for OpActionPanel
13389  OAListBox->Items->Add(L"");
13390  OAListBox->Items->Add(L"");
13391  OAListBox->Items->Add(L"Left click");
13392  OAListBox->Items->Add(L"headcode");
13393  OAListBox->Items->Add(L"to locate train");
13394  OAListBox->Items->Add(L"");
13395  OAListBox->Items->Add(L"");
13396  OAListBox->Items->Add(L"");
13397  OAListBox->Items->Add(L"");
13398  OAListBox->Items->Add(L"Left click and");
13399  OAListBox->Items->Add(L"hold grey area");
13400  OAListBox->Items->Add(L"to move panel");
13401  if((TrainController->AvHoursIntValue > 0) || (Level2OperMode == PreStart)) // only visible if already set or if still in prestart mode
13402  {
13403  MTBFEditBox->Visible = true;
13405  {
13406  MTBFEditBox->Text = AnsiString(TrainController->AvHoursIntValue);
13407  }
13408  else
13409  {
13410  MTBFEditBox->Text = "";
13411  }
13412  MTBFEditBox->ReadOnly = false; // because this is still prestart mode
13413  MTBFLabel->Visible = true;
13414  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
13416  }
13417  else
13418  {
13419  MTBFEditBox->Visible = false;
13420  MTBFEditBox->Text = "";
13421  MTBFEditBox->ReadOnly = true; // because this is not prestart mode
13422  MTBFLabel->Visible = false;
13423  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
13425  }
13426  break;
13427 
13428  default:
13429  // No further recursion in BaseMode so OK
13430  Level1Mode = BaseMode;
13431  SetLevel1Mode(29);
13432  break;
13433  }
13434  Utilities->CallLogPop(103);
13435 }
13436 
13437 // ---------------------------------------------------------------------------
13438 
13440 {
13441  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel2TrackMode");
13442  if(Level1Mode != TrackMode)
13443  {
13444  // No further recursion in BaseMode so OK
13445  Level1Mode = BaseMode;
13446  SetLevel1Mode(20);
13447  Utilities->CallLogPop(1115);
13448  return;
13449  }
13451  {
13452  Utilities->CallLogPop(104);
13453  return;
13454  }
13455  switch(Level2TrackMode) // use the data member
13456  {
13457  case AddTrack:
13459  InfoPanel->Visible = true;
13460  InfoPanel->Caption = "ADDING TRACK: Select element then left click to add it. Right click an element to remove it.";
13461  LengthConversionPanel->Visible = false; // in case had been in distance setting mode
13462  SpeedConversionPanel->Visible = false; // in case had been in distance setting mode
13463  TrackElementPanel->Visible = true;
13464  TrackElementPanel->Enabled = true;
13465  SigAspectButton->Visible = true;
13466  SigAspectButton->Enabled = true;
13467  ClearandRebuildRailway(34); // to replot grid if required & clear any other unwanted items
13469  SetLengthsButton->Enabled = false;
13470  if(Track->IsTrackFinished()) // can only set lengths for several elements together if TrackFinished
13471  {
13472  SetLengthsButton->Enabled = true;
13473  }
13474  UserGraphicReselectPanel->Visible = false;
13475  SelectLengthsFlag = false; // in case still set though probably won't be
13476  EditMenu->Enabled = true; //added at v2.6.0 to allow edits for an empty screen so track elements can fill a selected area
13477  break;
13478 
13479  case AddGraphic:
13480  InfoPanel->Visible = true;
13481  InfoPanel->Caption = "ADDING GRAPHIC: Left click layout to add SELECTED graphic, right click to remove ANY graphic.";
13482  break;
13483 
13484  case SelectGraphic:
13485  InfoPanel->Visible = true;
13486  InfoPanel->Caption = "SELECTING USER GRAPHIC: Select the graphic file then add as many as necessary to the layout.";
13487  break;
13488 
13489  case GapSetting:
13490  int HLoc, VLoc, Count;
13491  Count = Track->NumberOfGaps(0);
13492  if(div(Count, 2).rem == 1) // condition OK
13493  {
13494  ShowMessage("Can't connect, there are an odd number of gaps");
13496  SetLevel1Mode(77);
13498  // No further recursion in AddTrack so OK
13499  SetLevel2TrackMode(40);
13500  Utilities->CallLogPop(105);
13501  return;
13502  }
13503  if(!HighLightOneGap(2, HLoc, VLoc)) // condition OK
13504  // need to call this here to start gap setting process off,
13505  // called in MainScreenMouseDown hereafter. Function returns false for either a LocError (links not yet
13506  // complete) or no more gaps to be highlighted
13507  {
13508  // shouldn't reach here as later gaps covered in MainScreenMouseDown but leave & give error message
13509  ShowMessage("Error - Even number of gaps but all set after first call to HighLightOneGap");
13511  SetLevel1Mode(78);
13513  // No further recursion in AddTrack so OK
13514  SetLevel2TrackMode(41);
13515  Utilities->CallLogPop(106);
13516  return; // all gaps set
13517  }
13518  InfoPanel->Visible = true;
13519  InfoPanel->Caption = "CONNECTING GAPS: Click on connecting gap";
13520  UserGraphicReselectPanel->Visible = false;
13522  break;
13523 
13524  case AddText:
13525  InfoPanel->Visible = true;
13526  InfoPanel->Caption = "ADDING/EDITING TEXT: Left click to add, right click first letter to erase, or left click first letter to edit)";
13527  if(TextHandler->TextVectorSize(13) > 0)
13528  {
13529  MoveTextOrGraphicButton->Enabled = true;
13530  }
13531  else
13532  {
13533  MoveTextOrGraphicButton->Enabled = false;
13534  }
13535  UserGraphicReselectPanel->Visible = false;
13536  ClearandRebuildRailway(58); // to drop DistanceKey if was displayed
13537  break;
13538 
13539  case MoveTextOrGraphic:
13540  InfoPanel->Visible = true;
13541  InfoPanel->Caption = "MOVING TEXT OR GRAPHIC: If text left click first letter, if graphic left click anywhere, then drag";
13542  UserGraphicReselectPanel->Visible = false;
13543  ClearandRebuildRailway(59); // to drop DistanceKey if was displayed
13544  break;
13545 
13546  case AddLocationName:
13547  InfoPanel->Visible = true;
13548  InfoPanel->Caption = "NAMING LOCATIONS: Click on location element to add or change name";
13549  ClearandRebuildRailway(35); // to get rid of earlier red rectangle
13550  UserGraphicReselectPanel->Visible = false;
13551  SetTrackBuildImages(12);
13552  break;
13553 
13554  case DistanceStart:
13555  InfoPanel->Visible = true;
13556  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Select first location (only non-default elements marked)";
13557  DistanceKey->Visible = true;
13558  LengthConversionPanel->Visible = true;
13559  SpeedConversionPanel->Visible = true;
13560  UserGraphicReselectPanel->Visible = false;
13561  ClearandRebuildRailway(36); // to get rid of earlier unwanted markings
13562  break;
13563 
13564  case DistanceContinuing:
13565  InfoPanel->Visible = true;
13566  if(ConstructPrefDir->PrefDirSize() == 1)
13567  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Select next location";
13568  else
13569  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
13570  UserGraphicReselectPanel->Visible = false;
13571  ClearandRebuildRailway(54); // to remove earlier end marker if present
13572  break;
13573 
13574  case TrackSelecting:
13575  Track->CopyFlag = false;
13576  if(!SelectionValid)
13577  ResetSelectRect(); // so a viewpoint change before a new SelectRect chosen doesn't redisplay
13578  // the old SelectRect (only called when entered from SelectMenuItemClick, & not from
13579  // ReselectMenuItemClick)
13580  InfoPanel->Visible = true;
13581  InfoPanel->Caption = "SELECTING: Select area - click left mouse && drag";
13582  SelectMenuItem->Enabled = false;
13583  ReselectMenuItem->Enabled = false;
13584  CancelSelectionMenuItem->Enabled = true;
13585  UserGraphicReselectPanel->Visible = false;
13586  break;
13587 
13588  case CopyMoving:
13589  Track->CopyFlag = true;
13590  InfoPanel->Visible = true;
13591  InfoPanel->Caption = "COPYING: Left click in selection && drag";
13592  CutMenuItem->Enabled = false;
13593  CopyMenuItem->Enabled = false;
13594  FlipMenuItem->Enabled = false;
13595  MirrorMenuItem->Enabled = false;
13596  RotRightMenuItem->Enabled = false;
13597  RotLeftMenuItem->Enabled = false;
13598  RotateMenuItem->Enabled = false;
13599  PasteMenuItem->Enabled = true;
13600 // PasteWithAttributesMenuItem->Enabled = false; //new at v2.2.0 - don't allow the option if copying
13601  DeleteMenuItem->Enabled = false;
13602  SelectLengthsMenuItem->Enabled = false;
13603  SelectBiDirPrefDirsMenuItem->Visible = false;
13604  CancelSelectionMenuItem->Enabled = false;
13608  UserGraphicReselectPanel->Visible = false;
13609  break;
13610 
13611  case CutMoving:
13612  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
13613  // erase track elements within selected region
13614  Track->CopyFlag = false;
13615  bool EraseSuccessfulFlag, NeedToLink = false, TextChangesMade = false, GraphicChangesMade = false; ;
13616  int ErasedTrackVectorPosition;
13617  Screen->Cursor = TCursor(-11); // Hourglass;
13618  InfoPanel->Visible = true;
13619  InfoPanel->Caption = "CUT PROCESSING: Please do not click the mouse";
13620  InfoPanel->Update();
13621  for(int H = SelectRect.left; H < SelectRect.right; H++)
13622  {
13623  for(int V = SelectRect.top; V < SelectRect.bottom; V++)
13624  {
13625  Track->EraseTrackElement(2, H, V, ErasedTrackVectorPosition, EraseSuccessfulFlag, false);
13626  if(EraseSuccessfulFlag)
13627  {
13628  if(ErasedTrackVectorPosition > -1)
13629  EveryPrefDir->RealignAfterTrackErase(1, ErasedTrackVectorPosition);
13630  NeedToLink = true;
13631  }
13632  }
13633  }
13634  // erase text elements within selected region
13635  int LowSelectHPos = SelectRect.left * 16;
13636  int HighSelectHPos = SelectRect.right * 16;
13637  int LowSelectVPos = SelectRect.top * 16;
13638  int HighSelectVPos = SelectRect.bottom * 16;
13639  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
13640  {
13641  for(TTextHandler::TTextVectorIterator TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin();
13642  TextPtr--) // reverse to prevent skipping during erase
13643  {
13644  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
13645  HighSelectVPos))
13646  {
13647  if(TextHandler->TextErase(1, TextPtr->HPos, TextPtr->VPos, AnsiString("")))
13648  {;
13649  } // unused condition
13650  TextChangesMade = true;
13651  }
13652  }
13653  }
13654  // erase graphic elements that fall wholly within region to be overwritten
13655  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
13656  {
13657  for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->UserGraphicVector.end() - 1); GraphicPtr >= Track->UserGraphicVector.begin();
13658  GraphicPtr--) // reverse to prevent skipping during erase
13659  {
13660  if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
13661  && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
13662  {
13663  Track->UserGraphicVector.erase(GraphicPtr);
13664  GraphicChangesMade = true;
13665  }
13666  }
13667  }
13668  Track->CheckMapAndTrack(11); // test
13669  Track->CheckMapAndInactiveTrack(10); // test
13670  Track->CheckLocationNameMultiMap(19); // test
13671  Screen->Cursor = TCursor(-2); // Arrow;
13672  // Track->SetTrackFinished(!NeedToLink); This is an error (see Sam Wainwright email of 24/08/17 & devhistory.txt
13673  // if track not linked to begin with then becomes linked if NeedToLink false
13674  if(NeedToLink)
13675  Track->SetTrackFinished(false); // corrected for v2.1.0
13676  InfoPanel->Caption = "CUTTING: Left click in selection && drag";
13677  CutMenuItem->Enabled = false;
13678  CopyMenuItem->Enabled = false;
13679  FlipMenuItem->Enabled = false;
13680  MirrorMenuItem->Enabled = false;
13681  RotRightMenuItem->Enabled = false;
13682  RotLeftMenuItem->Enabled = false;
13683  RotateMenuItem->Enabled = false;
13684  PasteMenuItem->Enabled = true;
13685 // PasteWithAttributesMenuItem->Enabled = true; //new at v2.2.0 - option enabled if cutting
13686  DeleteMenuItem->Enabled = false;
13687  SelectLengthsMenuItem->Enabled = false;
13688  SelectBiDirPrefDirsMenuItem->Visible = false;
13689  CancelSelectionMenuItem->Enabled = false;
13692  if(NeedToLink || TextChangesMade || GraphicChangesMade)
13693  {
13694  ResetChangedFileDataAndCaption(20, true); // true for NonPrefDirChangesMade
13695  }
13696  ClearandRebuildRailway(37); // to overplot the erased elements with SelectBitmap
13697  UserGraphicReselectPanel->Visible = false;
13699  } break;
13700 
13701  case Pasting:
13702  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
13705  int HDiff = SelectBitmapHLoc - SelectRect.left;
13706  int VDiff = SelectBitmapVLoc - SelectRect.top;
13707  bool NeedToLink = false;
13708  bool TrackLinkingRequiredFlag;
13709  Screen->Cursor = TCursor(-11); // Hourglass;
13710  InfoPanel->Visible = true;
13711  InfoPanel->Caption = "PASTING: Please wait";
13712  InfoPanel->Update();
13713 // erase track elements
13714  int LowSelectHLoc = SelectBitmapHLoc;
13715  int HighSelectHLoc = SelectBitmapHLoc + (SelectBitmap->Width / 16);
13716  int LowSelectVLoc = SelectBitmapVLoc;
13717  int HighSelectVLoc = SelectBitmapVLoc + (SelectBitmap->Height / 16);
13718  bool TrackEraseSuccessfulFlag; // needed but not used here
13719  int ErasedTrackVectorPosition;
13720 // new quick method of erasing, only need H & V values
13721  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
13722  {
13723  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
13724  {
13725  Track->EraseTrackElement(5, x, y, ErasedTrackVectorPosition, TrackEraseSuccessfulFlag, false);
13726  if(ErasedTrackVectorPosition > -1)
13727  EveryPrefDir->RealignAfterTrackErase(2, ErasedTrackVectorPosition);
13728  }
13729  }
13730 
13731 // erase text elements that fall within region to be overwritten
13732  int LowSelectHPos = SelectBitmapHLoc * 16;
13733  int HighSelectHPos = (SelectBitmapHLoc * 16) + SelectBitmap->Width;
13734  int LowSelectVPos = SelectBitmapVLoc * 16;
13735  int HighSelectVPos = (SelectBitmapVLoc * 16) + SelectBitmap->Height;
13736  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
13737  {
13738  for(TTextHandler::TTextVectorIterator TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin();
13739  TextPtr--) // reverse to prevent skipping during erase
13740  {
13741  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
13742  HighSelectVPos))
13743  {
13744  if(TextHandler->TextErase(2, TextPtr->HPos, TextPtr->VPos, AnsiString("")))
13745  {;
13746  } // unused condition
13747  }
13748  }
13749  }
13750 // erase graphic elements that fall wholly within region to be overwritten
13751  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
13752  {
13753  for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->UserGraphicVector.end() - 1); GraphicPtr >= Track->UserGraphicVector.begin();
13754  GraphicPtr--) // reverse to prevent skipping during erase
13755  {
13756  if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
13757  && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
13758  {
13759  Track->UserGraphicVector.erase(GraphicPtr);
13760  }
13761  }
13762  }
13763  // change the H & V values in SelectVector to the new positions in case Reselect chosen
13764  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
13765  {
13766  Track->SelectVectorAt(35, x).HLoc += HDiff;
13767  Track->SelectVectorAt(1, x).VLoc += VDiff;
13768  }
13769 
13770  // add the new track elements
13771  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
13772  {
13773  if(Track->CopyFlag) // blank all names if copying, lengths & speedlimits stay
13774  {
13775  Track->SelectVectorAt(80, x).LocationName = "";
13777  }
13778  bool InternalChecks = false;
13779 // if(Track->PastingWithAttributes) //new at v2.2.0 to select the new funtion & skip multimap checks //drop in v2.4.0
13780 // {
13782  TrackLinkingRequiredFlag, InternalChecks);
13783  // new at v2.2.0 & used in place of PlotAndAddTrackElement to keep length & speed values
13784 // }
13785 /* drop this in v2.4.0 as all pastes are past with attributes
13786  else //'Aspect' parameter added to PlotAndAdd... at v2.2.0 so can plot signals correctly (always four-aspect before)
13787  {
13788  int Aspect;
13789  if(Track->SelectVectorAt(15, x).TrackType != SignalPost) Aspect = 0; //if an '0' value appears with a SignalPost then must be adding track
13790  //this combination allows the funtion to distinguish between adding track and plotting with attributes
13791  else if(Track->SelectVectorAt(16, x).SigAspect == TTrackElement::GroundSignal) Aspect = 1;
13792  else if(Track->SelectVectorAt(17, x).SigAspect == TTrackElement::TwoAspect) Aspect = 2;
13793  else if(Track->SelectVectorAt(18, x).SigAspect == TTrackElement::ThreeAspect) Aspect = 3;
13794  else Aspect = 4;
13795  Track->PlotAndAddTrackElement(2, Track->SelectVectorAt(19, x).SpeedTag, Aspect, Track->SelectVectorAt(20, x).HLoc, Track->SelectVectorAt(21, x).VLoc, TrackLinkingRequiredFlag, InternalChecks);
13796  }
13797 */
13798  if(TrackLinkingRequiredFlag)
13799  NeedToLink = true;
13800  }
13801 
13802  if(!TextHandler->SelectTextVector.empty()) // skip iteration if empty else have an error
13803  {
13804  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->SelectTextVector.begin(); TextPtr < TextHandler->SelectTextVector.end(); TextPtr++)
13805  {
13806  TextPtr->HPos += HDiff * 16;
13807  TextPtr->VPos += VDiff * 16;
13808  AnsiString TempString = TextPtr->TextString;
13809  // have to create a new TextItem in order to create a new Font object
13810 /* drop in v2.4.0 as all pastes are paste with attributes
13811  if(!Track->PastingWithAttributes) //new at v2.2.0 to deal with the new location prefix '##**' //drop in v2.4.0
13812  {
13813  if(TextPtr->TextString.SubString(1,4) != "##**") //added for named locations so can delete in a simple paste but
13814  //use in PastingWithAttributes
13815  {
13816  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, TextPtr->TextString, TextPtr->Font);
13817  TextHandler->TextVectorPush(0, TextItem); //if a normal paste include normal text but not location text
13818  }
13819  else TextPtr->TextString = ""; //delete the name for a simple paste
13820  }
13821 */
13822 // else //if pasting with attributes paste all text but strip the '##**' prefix if present
13823 // {
13824  if(TextPtr->TextString.SubString(1, 4) == "##**")
13825  {
13826  TempString = TextPtr->TextString.SubString(5, TextPtr->TextString.Length()); // don't change SelectTextVector value
13827  if(Track->CopyFlag)
13828  {
13829  TextPtr->TextString = ""; // change SelectTextVector value as reselect shouldn't have locations if copied
13830  TempString = "";
13831  }
13832  }
13833  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, TempString, TextPtr->Font);
13835 // }
13836  }
13837  }
13838  // add new graphic items
13839  if(!Track->SelectGraphicVector.empty()) // skip iteration if empty else have an error
13840  { // keep contents of SelectVector valid in case reselect
13841  for(TTrack::TUserGraphicVector::iterator GraphicPtr = Track->SelectGraphicVector.begin(); GraphicPtr < Track->SelectGraphicVector.end();
13842  GraphicPtr++)
13843  {
13844  GraphicPtr->HPos += HDiff * 16; // for reselect
13845  GraphicPtr->VPos += VDiff * 16; // for reselect
13846  Track->UserGraphicVector.push_back(*GraphicPtr);
13847  }
13848  }
13849  Track->SkipLocationNameMultiMapCheck = false; // renamed in v2.4.0 - reset the flag after pasting complete, otherwise multimap checks always skipped
13850  Track->CopyFlag = false;
13851  Track->CheckMapAndTrack(7); // test
13852  Track->CheckMapAndInactiveTrack(7); // test
13853  Track->CheckLocationNameMultiMap(7); // test
13854  // Track->SetTrackFinished(!NeedToLink); This is an error (see Sam Wainwright email of 24/08/17 & devhistory.txt
13855  // if track not linked to begin with then becomes linked if NeedToLink false
13856  if(NeedToLink)
13857  Track->SetTrackFinished(false); // corrected for v2.1.0
13858  Screen->Cursor = TCursor(-2); // Arrow;
13859  SetTrackBuildImages(14);
13862  SetLevel1Mode(79);
13864  // No further recursion in AddTrack so OK
13865  UserGraphicReselectPanel->Visible = false;
13866  SetLevel2TrackMode(42);
13867  } break;
13868 
13869  case Deleting:
13870  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
13871  Track->CopyFlag = false;
13872  UnicodeString MessageStr = "Selected area will be deleted - proceed?";
13873  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
13874  if(button == IDNO)
13875  {
13876  break;
13877  }
13878  bool EraseSuccessfulFlag, NeedToLink = false, TextChangesMade = false, GraphicChangesMade = false;
13879  int ErasedTrackVectorPosition;
13880  Screen->Cursor = TCursor(-11); // Hourglass;
13881  InfoPanel->Visible = true;
13882  InfoPanel->Caption = "DELETING: Please wait";
13883  InfoPanel->Update();
13884  for(int H = SelectRect.left; H < SelectRect.right; H++)
13885  {
13886  for(int V = SelectRect.top; V < SelectRect.bottom; V++)
13887  {
13888  Track->EraseTrackElement(3, H, V, ErasedTrackVectorPosition, EraseSuccessfulFlag, false);
13889  if(EraseSuccessfulFlag)
13890  {
13891  if(ErasedTrackVectorPosition > -1)
13892  EveryPrefDir->RealignAfterTrackErase(3, ErasedTrackVectorPosition);
13893  NeedToLink = true;
13894  }
13895  }
13896  }
13897  // erase text elements that fall within selected region
13898  int LowSelectHPos = SelectRect.left * 16;
13899  int HighSelectHPos = SelectRect.right * 16;
13900  int LowSelectVPos = SelectRect.top * 16;
13901  int HighSelectVPos = SelectRect.bottom * 16;
13902  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
13903  {
13904  for(TTextHandler::TTextVectorIterator TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin();
13905  TextPtr--) // reverse to prevent skipping during erase
13906  {
13907  AnsiString Check = TextPtr->TextString;
13908  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
13909  HighSelectVPos))
13910  {
13911  if(TextHandler->TextErase(3, TextPtr->HPos, TextPtr->VPos, AnsiString("")))
13912  {;
13913  } // unused condition
13914  TextChangesMade = true;
13915  }
13916  }
13917  }
13918  // erase graphic elements that fall within selected region
13919  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
13920  {
13921 
13922 //Isglassen05 (vilhelmgg@gmail.com) reported an error via email and attached an error file on 31/07/20. The error was in the following line which was:
13923 
13924 // for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->SelectGraphicVector.end() - 1); GraphicPtr >= Track->SelectGraphicVector.begin();
13925 // GraphicPtr--) // reverse to prevent skipping during erase
13926 
13927 //i.e if the railway included one or more user graphics but the SelectGraphicVector didn't include any, then GraphicPtr wouldn't point to anything and the program would fail
13928 //corrected 01/08/20 by using UserGraphicVector (as it should have been) for SelectGraphicVector. New version v2.4.3.
13929 
13930  for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->UserGraphicVector.end() - 1); GraphicPtr >= Track->UserGraphicVector.begin();
13931  GraphicPtr--) // reverse to prevent skipping during erase
13932  {
13933  if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
13934  && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
13935  {
13936  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = (Track->UserGraphicVector.end() - 1);
13937  UserGraphicPtr >= Track->UserGraphicVector.begin(); UserGraphicPtr--) // reverse to prevent skipping during erase
13938  {
13939  if((UserGraphicPtr->HPos == GraphicPtr->HPos) && (UserGraphicPtr->VPos == GraphicPtr->VPos) &&
13940  (UserGraphicPtr->Width == GraphicPtr->Width) && (UserGraphicPtr->Height == GraphicPtr->Height) &&
13941  (UserGraphicPtr->FileName == GraphicPtr->FileName))
13942  {
13943  Track->UserGraphicVector.erase(UserGraphicPtr);
13944  GraphicChangesMade = true;
13945  }
13946  }
13947  }
13948  }
13949  }
13950  // clear the selectvectors
13952  TextHandler->SelectTextVector.clear();
13953  Track->SelectGraphicVector.clear();
13954  Track->CheckMapAndTrack(10); // test
13955  Track->CheckMapAndInactiveTrack(9); // test
13956  Track->CheckLocationNameMultiMap(15); // test
13957  // Track->SetTrackFinished(!NeedToLink); This is an error (see Sam Wainwright email of 24/08/17 & devhistory.txt
13958  // if track not linked to begin with then becomes linked if NeedToLink false
13959  if(NeedToLink)
13960  Track->SetTrackFinished(false); // corrected for v2.1.0
13961  if(NeedToLink || TextChangesMade || GraphicChangesMade)
13962  {
13963  ResetChangedFileDataAndCaption(21, true); // true for NonPrefDirChangesMade
13964  }
13965  Screen->Cursor = TCursor(-2); // Arrow;
13968  SetLevel1Mode(80);
13970  // No further recursion in AddTrack so OK
13971  UserGraphicReselectPanel->Visible = false;
13972  SetLevel2TrackMode(43);
13973  } break;
13974 
13975  default:
13976  // No further recursion in TrackMode so OK
13977  Track->CopyFlag = false;
13979  SetLevel1Mode(21);
13980  UserGraphicReselectPanel->Visible = false;
13981  break;
13982  }
13983  Utilities->CallLogPop(107);
13984 }
13985 
13986 // ---------------------------------------------------------------------------
13987 
13989 {
13990  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel2PrefDirMode");
13991  if(Level1Mode != PrefDirMode)
13992  {
13993  // No further recursion in BaseMode so OK
13994  Level1Mode = BaseMode;
13995  SetLevel1Mode(22);
13996  Utilities->CallLogPop(108);
13997  return;
13998  }
14000  {
14001  Utilities->CallLogPop(109);
14002  return;
14003  }
14004 
14005  switch(Level2PrefDirMode) // use the data member
14006  {
14007  case PrefDirContinuing:
14008  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
14009  InfoPanel->Visible = true;
14010  if(!Display->ZoomOutFlag) // can't set focus if zoomed out, get an error - added this condition for v0.4d
14011  {
14012  AddPrefDirButton->Enabled = true; // this and the line below are to remove focus from any other button that might have it, prior to
14013  AddPrefDirButton->SetFocus(); // disabling the AddPrefDir button, so pressing enter does nothing, it is reset to the AddPrefDir
14014  }
14015  AddPrefDirButton->Enabled = false; // button later if it becomes enabled
14016  DeleteOnePrefDirButton->Enabled = false;
14017  bool LeadingPointsAtLastElement = false;
14018  if(!ConstructPrefDir->EndPossible(0, LeadingPointsAtLastElement))
14019  {
14020  if(LeadingPointsAtLastElement) // size must be > 1
14021  {
14022  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Can't end on leading points, select next location or truncate";
14023  DeleteOnePrefDirButton->Enabled = true;
14024  }
14025  else // size == 1, DeleteOnePrefDirButton->Enabled remains false
14026  {
14027  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Select next preferred direction location (right click to truncate)";
14028  }
14029  }
14030  else // size > 1 & EndPossible
14031  {
14032  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Add selection or select next location (right click to truncate)";
14033  if(!Display->ZoomOutFlag) // can't set focus if zoomed out, get an error - added this condition for v0.4d
14034  {
14035  AddPrefDirButton->Enabled = true;
14036  AddPrefDirButton->SetFocus(); // so can just press 'Enter' key
14037  }
14038  DeleteOnePrefDirButton->Enabled = true;
14039  }
14040  ExitPrefDirButton->Enabled = true;
14041  ClearandRebuildRailway(40); // to show truncated PrefDirs
14042  } break;
14043 
14044  case PrefDirSelecting:
14045  ResetSelectRect(); // so a viewpoint change before a new SelectRect chosen doesn't redisplay the old SelectRect
14046  InfoPanel->Visible = true;
14047  InfoPanel->Caption = "SELECTING: Select area - click left mouse && drag";
14048  SelectMenuItem->Enabled = false;
14049  ReselectMenuItem->Enabled = false;
14050  CancelSelectionMenuItem->Enabled = true;
14051  break;
14052 
14053  default:
14054  // No further recursion in PrefDirMode so OK
14056  SetLevel1Mode(23);
14057  break;
14058  }
14059  Utilities->CallLogPop(110);
14060 }
14061 
14062 // ---------------------------------------------------------------------------
14063 
14065 {
14066  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel2OperMode");
14067  if(Level1Mode != OperMode)
14068  {
14069  // No further recursion in BaseMode so OK
14070  Level1Mode = BaseMode;
14071  SetLevel1Mode(24);
14072  Utilities->CallLogPop(111);
14073  return;
14074  }
14075  if(Level2OperMode == NoOperMode)
14076  {
14077  Utilities->CallLogPop(112);
14078  return;
14079  }
14080  CallingOnButton->Visible = true;
14081  PresetAutoSigRoutesButton->Visible = false;
14082  switch(Level2OperMode) // use the data member
14083  {
14084  case Operating:
14085  { // have to use braces as otherwise the default case bypasses the initialisation of local variables
14086  OperateButton->Enabled = true;
14087  OperateButton->Glyph->LoadFromResourceName(0, "PauseGraphic");
14088  ExitOperationButton->Enabled = true;
14089  TTClockAdjButton->Enabled = false;
14090  if(TTClockSpeed == 2)
14091  TTClockSpeedLabel->Caption = "x2";
14092  else if(TTClockSpeed == 4)
14093  TTClockSpeedLabel->Caption = "x4";
14094  else if(TTClockSpeed == 8)
14095  TTClockSpeedLabel->Caption = "x8";
14096  else if(TTClockSpeed == 16)
14097  TTClockSpeedLabel->Caption = "x16";
14098  else if(TTClockSpeed == 0.5)
14099  TTClockSpeedLabel->Caption = "x1/2";
14100  else if(TTClockSpeed == 0.25)
14101  TTClockSpeedLabel->Caption = "x1/4";
14102  else if(TTClockSpeed == 0.125)
14103  TTClockSpeedLabel->Caption = "x1/8";
14104  else if(TTClockSpeed == 0.0625)
14105  TTClockSpeedLabel->Caption = "x1/16";
14106  else
14107  {
14108  TTClockSpeed = 1;
14109  TTClockSpeedLabel->Caption = "x1";
14110  }
14111  AnsiString TimeMessage = Utilities->Format96HHMMSS(TDateTime(PauseEntryRestartTime)) + ": ";
14113  {
14114  // send message to performance log
14115  if(TTClockSpeed == 2)
14116  Display->PerformanceLog(6, TimeMessage + "Timetable clock speed changed to twice normal");
14117  else if(TTClockSpeed == 4)
14118  Display->PerformanceLog(7, TimeMessage + "Timetable clock speed changed to four times normal");
14119  else if(TTClockSpeed == 8)
14120  Display->PerformanceLog(8, TimeMessage + "Timetable clock speed changed to eight times normal");
14121  else if(TTClockSpeed == 16)
14122  Display->PerformanceLog(9, TimeMessage + "Timetable clock speed changed to sixteen times normal");
14123  else if(TTClockSpeed == 0.5)
14124  Display->PerformanceLog(10, TimeMessage + "Timetable clock speed changed to half normal");
14125  else if(TTClockSpeed == 0.25)
14126  Display->PerformanceLog(11, TimeMessage + "Timetable clock speed changed to quarter normal");
14127  else if(TTClockSpeed == 0.125)
14128  Display->PerformanceLog(14, TimeMessage + "Timetable clock speed changed to one eighth normal");
14129  else if(TTClockSpeed == 0.0625)
14130  Display->PerformanceLog(15, TimeMessage + "Timetable clock speed changed to one sixteenth normal");
14131  else
14132  Display->PerformanceLog(12, TimeMessage + "Timetable clock speed changed to normal");
14133  }
14134  double TTClockTimeChange = double(TrainController->RestartTime) - PauseEntryRestartTime;
14135  if(TTClockTimeChange > 0.000347) // 30 seconds, min increase is 1 minute & don't trust doubles to stay exactly equal
14136  {
14137  // send message to performance log
14138  int MinsIncrease = ((TTClockTimeChange * 1440) + 0.5); // add 30 secs to ensure truncates correctly
14139  int HoursIncrease = 0;
14140  while(MinsIncrease >= 60)
14141  {
14142  HoursIncrease++;
14143  MinsIncrease -= 60;
14144  }
14145  if(HoursIncrease == 0)
14146  TimeMessage += "Timetable clock incremented by " + AnsiString(MinsIncrease) + "m";
14147  else if(MinsIncrease == 0)
14148  TimeMessage += "Timetable clock incremented by " + AnsiString(HoursIncrease) + "h";
14149  else
14150  TimeMessage += "Timetable clock incremented by " + AnsiString(HoursIncrease) + "h " + AnsiString(MinsIncrease) + "m";
14151  Display->PerformanceLog(13, TimeMessage);
14152  }
14153  WarningHover = false;
14156  {
14157  MTBFEditBox->Visible = true;
14158  MTBFEditBox->Text = AnsiString(TrainController->AvHoursIntValue);
14159  MTBFEditBox->ReadOnly = true; // because this is not prestart mode
14160  MTBFLabel->Visible = true;
14161  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
14163  }
14164  else
14165  {
14166  MTBFEditBox->Visible = false;
14167  MTBFEditBox->Text = "";
14168  MTBFLabel->Visible = false;
14169  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
14171  }
14172  TrainController->BaseTime = TDateTime::CurrentDateTime();
14173 // StopTTClockFlag already false because TTClock stopped by condition "if(!TrainController->StopTTClockFlag && (Level2OperMode == Operating))" in MasterClockTimer function
14174  } break;
14175 
14176  case Paused:
14177  OperateButton->Enabled = true;
14178  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
14179  ExitOperationButton->Enabled = true;
14180  TTClockAdjButton->Enabled = true;
14185 // StopTTClockFlag stays false because TTClock stopped by condition "if(!TrainController->StopTTClockFlag && (Level2OperMode == Operating))" in MasterClockTimer function
14188  break;
14189 
14190  // don't need a separate case for PreStart
14191 
14192  default:
14193  // No further recursion in OperMode so OK
14194  Level1Mode = OperMode;
14195  SetLevel1Mode(25);
14196  break;
14197  }
14198  Utilities->CallLogPop(113);
14199 }
14200 
14201 // ---------------------------------------------------------------------------
14202 
14203 void TInterface::ApproachLocking(int Caller, TDateTime TTClockTime)
14204 {
14205  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ApproachLocking");
14206  float LockDelay = 120.0;
14207 
14208  if(!AllRoutes->LockedRouteVector.empty())
14209  {
14210  for(TAllRoutes::TLockedRouteVectorIterator LRVIT = AllRoutes->LockedRouteVector.end() - 1; LRVIT >= AllRoutes->LockedRouteVector.begin(); LRVIT--)
14211  {
14212  bool BreakFlag = false;
14213  if(AllRoutes->TrackIsInARoute(5, LRVIT->LastTrackVectorPosition, LRVIT->LastXLinkPos))
14214  {
14215  TOneRoute &Route = AllRoutes->GetModifiableRouteAt(0, LRVIT->RouteNumber);
14216  if((TTClockTime - LRVIT->LockStartTime) > TDateTime(LockDelay / 86400))
14217  {
14218  TrainController->LogEvent("LockedRouteRemoved," + AnsiString(LRVIT->TruncateTrackVectorPosition) + "," +
14219  AnsiString(LRVIT->LastTrackVectorPosition));
14220  while(Route.LastElementPtr(9)->GetTrackVectorPosition() != LRVIT->TruncateTrackVectorPosition)
14221  { // examine the element one earlier in the route than the last
14222  if(!(AllRoutes->TrackIsInARoute(6, Route.LastElementPtr(10)->Conn[Route.LastElementPtr(11)->GetELinkPos()],
14223  Route.LastElementPtr(12)->ConnLinkPos[Route.LastElementPtr(13)->GetELinkPos()])))
14224  {
14225  BreakFlag = true;
14226  }
14227  AllRoutes->RemoveRouteElement(1, Route.LastElementPtr(14)->HLoc, Route.LastElementPtr(15)->VLoc, Route.LastElementPtr(16)->GetELink());
14228  if(BreakFlag)
14229  break; // train removed earlier element from route so stop here
14230  }
14231  if(!BreakFlag)
14232  { // still need to remove the element at the TruncateTrackVectorPosition
14233  if(Route.LastElementPtr(17)->GetTrackVectorPosition() == LRVIT->TruncateTrackVectorPosition)
14234  {
14235  AllRoutes->RemoveRouteElement(2, Route.LastElementPtr(18)->HLoc, Route.LastElementPtr(19)->VLoc,
14236  Route.LastElementPtr(20)->GetELink());
14237  }
14238  }
14239  AllRoutes->CheckMapAndRoutes(10); // test
14240  AllRoutes->LockedRouteVector.erase(LRVIT);
14241  if(!Display->ZoomOutFlag)
14242  ClearandRebuildRailway(17); // to get rid of route graphics
14244  }
14245  }
14246  else
14247  {
14248  AllRoutes->LockedRouteVector.erase(LRVIT);
14249  // if end element not in route then a train must have entered it from the wrong end and erased the whole route,
14250  // hence no longer needed so get rid of it
14251  }
14252  }
14253  }
14254  Utilities->CallLogPop(743);
14255 }
14256 
14257 // ---------------------------------------------------------------------------
14258 
14259 void TInterface::ContinuationAutoSignals(int Caller, TDateTime TTClockTime)
14260 {
14261  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ContinuationAutoSignals");
14263  {
14265  for(AutoSigVectorIT = TrainController->ContinuationAutoSigVector.end() - 1; AutoSigVectorIT >= TrainController->ContinuationAutoSigVector.begin();
14266  AutoSigVectorIT--)
14267  {
14268  // Below added at v2.1.0 to prevent locked autosig continuation routes from clearing signals
14269  // need to identify the Continuation element in the route & check if it's in a locked route. If it is then don't call
14270  // SetTrailingSignalsOnContinuationRoute as all signals must stay red.
14271  TPrefDirElement TempPrefDirElement;
14272  int TempLockedVectorNumber;
14273  int LastRouteElement = AllRoutes->GetFixedRouteAt(220, AutoSigVectorIT->RouteNumber).PrefDirSize() - 1;
14274  int TVNum = AllRoutes->GetFixedRouteAt(221, AutoSigVectorIT->RouteNumber).GetFixedPrefDirElementAt(246, LastRouteElement).GetTrackVectorPosition();
14275  // this will be a continuation (error thrown in SetTrailingSignalsOnContinuationRoute if not) & XLinkPos is always 0 for
14276  // route exiting at a continuation
14277  if(AllRoutes->IsElementInLockedRouteGetPrefDirElementGetLockedVectorNumber(14, TVNum, 0, TempPrefDirElement, TempLockedVectorNumber))
14278  {
14279  continue;
14280  }
14281  // end of additions
14282  if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->FirstDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 0))
14283  {
14284  AllRoutes->SetTrailingSignalsOnContinuationRoute(1, AutoSigVectorIT->RouteNumber, 0);
14285  AutoSigVectorIT->AccessNumber++;
14286  continue;
14287  }
14288  if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->SecondDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 1))
14289  {
14290  AllRoutes->SetTrailingSignalsOnContinuationRoute(2, AutoSigVectorIT->RouteNumber, 1);
14291  AutoSigVectorIT->AccessNumber++;
14292  continue;
14293  }
14294  if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->ThirdDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 2))
14295  {
14296  AllRoutes->SetTrailingSignalsOnContinuationRoute(3, AutoSigVectorIT->RouteNumber, 2);
14297  AutoSigVectorIT->AccessNumber++;
14298  continue;
14299  }
14300  }
14301  // examine all vector for any expired values & erase
14302  for(AutoSigVectorIT = TrainController->ContinuationAutoSigVector.end() - 1; AutoSigVectorIT >= TrainController->ContinuationAutoSigVector.begin();
14303  AutoSigVectorIT--)
14304  {
14305  if(AutoSigVectorIT->AccessNumber > 2)
14306  {
14307  TrainController->ContinuationAutoSigVector.erase(AutoSigVectorIT); // erase expired entries - reverse interation so OK to erase
14308  }
14309  }
14310  }
14311  Utilities->CallLogPop(744);
14312 }
14313 
14314 // ---------------------------------------------------------------------------
14315 
14317 {
14318  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",TrackTrainFloat");
14319 
14320  TPoint MousePoint = Mouse->CursorPos;
14321  int ScreenX = MousePoint.x - MainScreen->ClientOrigin.x;
14322  int ScreenY = MousePoint.y - MainScreen->ClientOrigin.y;
14323 
14324  if((ScreenX > (MainScreen->Width - 1)) || (ScreenY > (MainScreen->Height - 1)) || (ScreenX < 0) || (ScreenY < 0))
14325  {
14326  FloatingPanel->Visible = false;
14327  Utilities->CallLogPop(1432);
14328  return;
14329  }
14330 
14331  if(PerformancePanel->Visible)
14332  {
14333  if((MousePoint.x >= PerformancePanel->Left) && (MousePoint.x <= (PerformancePanel->Left + PerformancePanel->Width)) &&
14334  ((MousePoint.y - ClientOrigin.y) >= PerformancePanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
14335  (PerformancePanel->Top + PerformancePanel->Height)))
14336  { // dont show floating window if mouse over performance panel
14337  FloatingPanel->Visible = false;
14338  Utilities->CallLogPop(1715);
14339  return;
14340  }
14341  }
14342 
14343  if(OperatorActionPanel->Visible) // added at v2.3.0 as showed info from behind panel - thanks to Xeon who notified me in email of 15/10/19
14344  {
14345  if((MousePoint.x >= OperatorActionPanel->Left) && (MousePoint.x <= (OperatorActionPanel->Left + OperatorActionPanel->Width)) &&
14346  ((MousePoint.y - ClientOrigin.y) >= OperatorActionPanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
14347  (OperatorActionPanel->Top + OperatorActionPanel->Height)))
14348  { // dont show floating window if mouse over OperatorActionPanel
14349  FloatingPanel->Visible = false;
14350  Utilities->CallLogPop(2098);
14351  return;
14352  }
14353  }
14354 
14355  if(TimetableEditPanel->Visible) // added at v2.5.1 as showed track info behind panel
14356  {
14357  if((MousePoint.x >= TimetableEditPanel->Left) && (MousePoint.x <= (TimetableEditPanel->Left + TimetableEditPanel->Width)) &&
14358  ((MousePoint.y - ClientOrigin.y) >= TimetableEditPanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
14359  (TimetableEditPanel->Top + TimetableEditPanel->Height)))
14360  { // dont show floating window if mouse over TimetableEditPanel
14361  FloatingPanel->Visible = false;
14362  Utilities->CallLogPop(2240);
14363  return;
14364  }
14365  }
14366 
14367  AnsiString TrackFloat = "", TrainStatusFloat = "", TrainTTFloat = "";
14368 
14369  bool ShowTrackFloatFlag = false, ShowTrainStatusFloatFlag = false, ShowTrainTTFloatFlag = false;
14370  int HLoc, VLoc;
14371 
14372  Track->GetTrackLocsFromScreenPos(4, HLoc, VLoc, ScreenX, ScreenY);
14373 
14374  if(Display->ZoomOutFlag)
14375  {
14376  Utilities->CallLogPop(1123);
14377  return;
14378  }
14379  if(TrackInfoOnOffMenuItem->Caption == "Hide")
14380  {
14381  bool ActiveTrackFoundFlag = false, InactiveTrackFoundFlag = false, TwoTrack = false;
14382  AnsiString Length01Str = "", Length23Str = "", SpeedLimit01Str = "", SpeedLimit23Str = "";
14383  AnsiString StationEntryStopLinkPos1Str = "", StationEntryStopLinkPos2Str = "";
14384  AnsiString ATrackSN = "", ATrackTN = "", IATrackSN = "", LengthAndSpeedCaption = "";
14385  AnsiString SigAspectString = ""; // new at version 0.6
14386  int ActiveVecPos = Track->GetVectorPositionFromTrackMap(5, HLoc, VLoc, ActiveTrackFoundFlag);
14387  TTrack::TIMPair InactiveVecPositions = Track->GetVectorPositionsFromInactiveTrackMap(3, HLoc, VLoc, InactiveTrackFoundFlag);
14388  TTrackElement ActiveTrackElement, InactiveTrackElement;
14389  if(InactiveTrackFoundFlag)
14390  {
14391  InactiveTrackElement = Track->InactiveTrackElementAt(32, InactiveVecPositions.first); // only need one for the name
14392  IATrackSN = InactiveTrackElement.LocationName;
14393  }
14394  if(ActiveTrackFoundFlag)
14395  {
14396  ActiveTrackElement = Track->TrackElementAt(449, ActiveVecPos);
14397  ATrackSN = ActiveTrackElement.LocationName;
14398  StationEntryStopLinkPos1Str = AnsiString(ActiveTrackElement.StationEntryStopLinkPos1);
14399  StationEntryStopLinkPos2Str = AnsiString(ActiveTrackElement.StationEntryStopLinkPos2);
14400  ATrackTN = ActiveTrackElement.ActiveTrackElementName;
14401  if((ATrackTN != "") && (!InactiveTrackFoundFlag || ((InactiveTrackElement.TrackType != Platform) &&
14402  (InactiveTrackElement.TrackType != NamedNonStationLocation)) ||
14403  (InactiveTrackElement.LocationName != ActiveTrackElement.ActiveTrackElementName)))
14404  {
14405  ShowMessage("Error - Track has timetable name without corresponding plat/named loc");
14406  }
14407  if(InactiveTrackFoundFlag && ((InactiveTrackElement.TrackType == Platform) || (InactiveTrackElement.TrackType == NamedNonStationLocation)) &&
14408  (InactiveTrackElement.LocationName != ActiveTrackElement.ActiveTrackElementName))
14409  {
14410  ShowMessage("Error - plat/named loc and track have different names, or plat/named loc named but not track");
14411  }
14412  if((ActiveTrackElement.TrackType == Points) || (ActiveTrackElement.TrackType == Bridge) || (ActiveTrackElement.TrackType == Crossover))
14413  {
14414  TwoTrack = true;
14415  }
14416  Length01Str = AnsiString(ActiveTrackElement.Length01);
14417  if(Length01Str == "-1")
14418  Length01Str = "Not Set";
14419  SpeedLimit01Str = AnsiString(ActiveTrackElement.SpeedLimit01);
14420  if(SpeedLimit01Str == "-1")
14421  SpeedLimit01Str = "Not Set";
14422  if(TwoTrack)
14423  {
14424  Length23Str = AnsiString(ActiveTrackElement.Length23);
14425  if(Length23Str == "-1")
14426  Length23Str = "Not Set"; // shouldn't be -1 but leave in
14427  SpeedLimit23Str = AnsiString(ActiveTrackElement.SpeedLimit23);
14428  if(SpeedLimit23Str == "-1")
14429  SpeedLimit23Str = "Not Set"; // shouldn't be -1 but leave in
14430  if((ActiveTrackElement.TrackType == Points) && (ActiveTrackElement.SpeedTag < 132))
14431  {
14432  LengthAndSpeedCaption = "Straight track length = " + Length01Str + " m" + '\n' + "Diverging track length = " + Length23Str + " m" + '\n' +
14433  "Straight track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Diverging track speed limit = " + SpeedLimit23Str + " km/h";
14434  }
14435  else if(ActiveTrackElement.TrackType == Points)
14436  {
14437  LengthAndSpeedCaption = "Left diverging track length = " + Length01Str + " m" + '\n' + "Right diverging track length = " + Length23Str +
14438  " m" + '\n' + "Left diverging track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Right diverging track Speed Limit = " +
14439  SpeedLimit23Str + " km/h";
14440  }
14441  else if(ActiveTrackElement.TrackType == Crossover)
14442  // crossover links 0 & 1 = diagonal top left to Bottom right, then horizontal, then vertical
14443  {
14444  if((ActiveTrackElement.SpeedTag == 15) || (ActiveTrackElement.SpeedTag == 46))
14445  {
14446  LengthAndSpeedCaption = "Horizontal track length = " + Length01Str + " m" + '\n' + "Other track length = " + Length23Str + " m" + '\n' +
14447  "Horizontal track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit23Str + " km/h";
14448  }
14449  else if(ActiveTrackElement.SpeedTag == 47)
14450  {
14451  LengthAndSpeedCaption = "Horizontal track length = " + Length23Str + " m" + '\n' + "Other track length = " + Length01Str + " m" + '\n' +
14452  "Horizontal track speed limit = " + SpeedLimit23Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit01Str + " km/h";
14453  }
14454  else if(ActiveTrackElement.SpeedTag == 45)
14455  {
14456  LengthAndSpeedCaption = "Vertical track length = " + Length01Str + " m" + '\n' + "Other track length = " + Length23Str + " m" + '\n' +
14457  "Vertical track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit23Str + " km/h";
14458  }
14459  else if(ActiveTrackElement.SpeedTag == 44)
14460  {
14461  LengthAndSpeedCaption = "Vertical track length = " + Length23Str + " m" + '\n' + "Other track length = " + Length01Str + " m" + '\n' +
14462  "Vertical track speed limit = " + SpeedLimit23Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit01Str + " km/h";
14463  }
14464  else if(ActiveTrackElement.SpeedTag == 16)
14465  {
14466  LengthAndSpeedCaption = "Top left to bottom right track length = " + Length01Str + " m" + '\n' + "Other track length = " + Length23Str +
14467  " m" + '\n' + "Top left to bottom right track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Other track speed limit = " +
14468  SpeedLimit23Str + " km/h";
14469  }
14470  }
14471  else // bridge
14472  {
14473  LengthAndSpeedCaption = "Top track length = " + Length01Str + " m" + '\n' + "Bottom track length = " + Length23Str + " m" + '\n' +
14474  "Top track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Bottom track speed limit = " + SpeedLimit23Str + " km/h";
14475  }
14476  }
14477  else
14478  {
14479  LengthAndSpeedCaption = "Track length = " + Length01Str + " m" + '\n' + "Track speed limit = " + SpeedLimit01Str + " km/h";
14480  }
14481  }
14482  if(ActiveTrackFoundFlag)
14483  {
14484  // note that now the "In timetable..." line removed much of the below could be simplified, but leave as is
14485  // in case wish to resurrect this line for any reason
14486  ShowTrackFloatFlag = true;
14487  if(ATrackTN != "") // has a timetable name & therefore has a valid platform or non-station name
14488  {
14489  TrackFloat = "Location = " + ATrackTN + '\n' + LengthAndSpeedCaption + '\n' + "ID = " + AnsiString(ActiveTrackElement.ElementID);
14490  }
14491  else if(ATrackSN != "") // no timetable name but location name, i.e. a footcrossing
14492  {
14493  TrackFloat = "Location = " + ATrackSN + '\n' + LengthAndSpeedCaption + '\n' + "ID = " + AnsiString(ActiveTrackElement.ElementID);
14494  }
14495 
14496  else if(InactiveTrackFoundFlag) // no timetable name yet but unnamed inactive element at same location (can't be a parapet if active element there)
14497  {
14498  TrackFloat = "Location unnamed\n" + LengthAndSpeedCaption + '\n' + "ID = " + AnsiString(ActiveTrackElement.ElementID);
14499  }
14500 
14501  else // no timetable or location name, just track
14502  {
14503  TrackFloat = LengthAndSpeedCaption + '\n' + "Track Element ID = " + AnsiString(ActiveTrackElement.ElementID);
14504  }
14505  if(ActiveTrackElement.TrackType == SignalPost) // new for version 0.6
14506  {
14507  if(ActiveTrackElement.SigAspect == TTrackElement::ThreeAspect)
14508  {
14509  SigAspectString = "\nThree-aspect signal";
14510  }
14511  else if(ActiveTrackElement.SigAspect == TTrackElement::TwoAspect)
14512  {
14513  SigAspectString = "\nTwo-aspect signal";
14514  }
14515  else if(ActiveTrackElement.SigAspect == TTrackElement::GroundSignal)
14516  {
14517  SigAspectString = "\nGround signal";
14518  }
14519  else
14520  {
14521  SigAspectString = "\nFour-aspect signal";
14522  }
14523  TrackFloat += SigAspectString;
14524  }
14525  } // if(ActiveFoundFlag)
14526  else if(InactiveTrackFoundFlag) // inactive element but no active element,
14527  // i.e. concourse or non-station name at a blank element
14528  {
14529  ShowTrackFloatFlag = true;
14530  if(InactiveTrackElement.TrackType != Parapet)
14531  {
14532  if(IATrackSN == "")
14533  {
14534  TrackFloat = "Location unnamed\nID = " + AnsiString(InactiveTrackElement.ElementID);
14535  }
14536  else
14537  {
14538  TrackFloat = "Location = " + IATrackSN + '\n' + "ID = " + AnsiString(InactiveTrackElement.ElementID);
14539  }
14540  }
14541  else // it is a parapet, just show the ID
14542  {
14543  TrackFloat = "ID = " + AnsiString(InactiveTrackElement.ElementID);
14544  }
14545  }
14546  }
14547 // end of TrackFloat section
14548 
14549  if(Level1Mode == OperMode && ((TrainStatusInfoOnOffMenuItem->Caption == "Hide Status") || (TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")))
14550  // if caption is 'Hide' label is required
14551  {
14552  bool FoundFlag;
14553  AnsiString FormatOneDPStr = "####0.0";
14554  AnsiString FormatNoDPStr = "#######0";
14555 // AnsiString Format5DPStr = "####0.00000"; //temporary
14556  AnsiString MaxBrakeStr = ""; // , EntrySpeedStr="", HalfStr="", FullStr="", MaxAtHalfStr="";//test
14557  AnsiString SpecialStr = "", MaxSpeedStr = "";
14558  int VecPos = Track->GetVectorPositionFromTrackMap(6, HLoc, VLoc, FoundFlag);
14559  if(FoundFlag)
14560  {
14561  if(Track->TrackElementAt(450, VecPos).TrainIDOnElement > -1)
14562  // if a bridge & 2 trains at that position will select the train with TrainIDOnElement set
14563  {
14565  if(TrainStatusInfoOnOffMenuItem->Caption == "Hide Status")
14566  {
14567  ShowTrainStatusFloatFlag = true;
14568  AnsiString HeadCode = "", ServiceReferenceInfo = "", Status = "", CurrSpeedStr = "", BrakePCStr = "", NextStopStr = "", TimeLeftStr = "",
14569  TimeToNextMovementStr = "", MassStr = "", PowerStr = "";
14570  double CurrSpeed;
14571  MassStr = AnsiString::FormatFloat(FormatNoDPStr, ((double)Train.Mass) / 1000); // Te
14572  PowerStr = AnsiString::FormatFloat(FormatNoDPStr, Train.PowerAtRail / 1000 / 0.8); // kW
14573  if(Train.BeingCalledOn)
14574  MaxSpeedStr = "30";
14575  else
14576  MaxSpeedStr = AnsiString::FormatFloat(FormatNoDPStr, Train.MaxRunningSpeed);
14577  TDateTime ElapsedDeltaT = TrainController->TTClockTime - Train.EntryTime;
14578  TDateTime FirstHalfTimeDeltaT = Train.ExitTimeHalf - Train.EntryTime;
14579  TDateTime SecondHalfTimeDeltaT = Train.ExitTimeFull - Train.EntryTime - FirstHalfTimeDeltaT;
14580  TDateTime TimeLeft;
14581  double BrakePCRate = Train.BrakeRate * 100.0 / Train.MaxBrakeRate;
14582  MaxBrakeStr = AnsiString::FormatFloat(FormatNoDPStr, (Train.MaxBrakeRate * Train.Mass / 9810));
14583  HeadCode = Train.HeadCode;
14584  if(Train.TrainDataEntryPtr->NumberOfTrains > 1) // Service reference information added at v0.6b
14585  {
14586  if(Train.RepeatNumber == 0)
14587  {
14588  if(HeadCode != Train.TrainDataEntryPtr->ServiceReference)
14589  ServiceReferenceInfo = "\nFirst service of ref. " + Train.TrainDataEntryPtr->ServiceReference;
14590  else
14591  ServiceReferenceInfo = "\nFirst service";
14592  }
14593  else if(HeadCode == Train.TrainDataEntryPtr->ServiceReference)
14594  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(Train.RepeatNumber);
14595  else
14596  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(Train.RepeatNumber) + " of ref. " +
14598  }
14599  else
14600  {
14601  if(HeadCode != Train.TrainDataEntryPtr->ServiceReference)
14602  ServiceReferenceInfo = "\nService reference " + Train.TrainDataEntryPtr->ServiceReference;
14603  }
14604  if(Train.Stopped())
14605  {
14606  if(Train.SignallerStopped)
14607  Status = "Stopped on signaller's instruction"; // if stopped for any other reason that will diplay
14608  if(Train.NotInService)
14609  Status = "Not in service"; // not used so far but leave it in
14610  if(Train.StoppedAtBuffers)
14611  Status = "Stopped at buffers";
14612  if(Train.StoppedAtSignal)
14613  Status = "Stopped at signal";
14614  if(Train.StoppedForTrainInFront)
14615  Status = "Stopped - forward track occupied"; // before station stop as want to display station stop if that set
14616  if(Train.StoppedAtLocation)
14617  Status = "Stopped at " + Train.ActionVectorEntryPtr->LocationName;
14618  if((Train.StoppedAtLocation) && (Train.StoppedForTrainInFront))
14619  Status = "Stopped at " + Train.ActionVectorEntryPtr->LocationName + " + forward track occupied";
14620  if(Train.StoppedWithoutPower)
14621  {
14622  if(Train.TrainFailed)
14623  Status = "Stopped without power - train failed";
14624  else
14625  Status = "Stopped without power";
14626  }
14627  if(Train.StoppedAfterSPAD)
14628  Status = "Stopped - signal passed at danger";
14629  if(Train.Derailed)
14630  Status = "Derailed";
14631  if(Train.Crashed)
14632  Status = "Crashed";
14633  CurrSpeed = 0;
14634  }
14635  else if(Train.OneLengthAccelDecel)
14636  {
14637  if(Train.FirstHalfMove)
14638  {
14639  Status = "Accelerating"; // just display a linear speed rise over half length
14640  BrakePCRate = 0; // reset to proper value during braking
14641  CurrSpeed = Train.EntrySpeed + ((Train.ExitSpeedHalf - Train.EntrySpeed) * (double(ElapsedDeltaT) / double(FirstHalfTimeDeltaT)));
14642  }
14643  else
14644  {
14645  BrakePCRate = Train.BrakeRate * 100.0 / Train.MaxBrakeRate;
14646  if(BrakePCRate < 55)
14647  Status = "Light braking";
14648  else if(BrakePCRate < 90)
14649  Status = "Heavy braking";
14650  else
14651  Status = "Emergency braking";
14652  CurrSpeed = Train.ExitSpeedHalf - 3.6 * (Train.BrakeRate * (TrainController->TTClockTime - Train.ExitTimeHalf) * 86400.0);
14653  }
14654  }
14655  else if(Train.BrakeRate > 0.01)
14656  {
14657  if(BrakePCRate < 55)
14658  Status = "Light braking";
14659  else if(BrakePCRate < 90)
14660  Status = "Heavy braking";
14661  else
14662  Status = "Emergency braking";
14663  CurrSpeed = Train.EntrySpeed - 3.6 * (Train.BrakeRate * ElapsedDeltaT * 86400.0);
14664  }
14665 
14666  else if((Train.BrakeRate <= 0.01) && (Train.ExitSpeedHalf > (Train.EntrySpeed + 0.01)) && Train.FirstHalfMove)
14667  {
14668  Status = "Accelerating"; // just display a linear speed rise over half length
14669  CurrSpeed = Train.EntrySpeed + ((Train.ExitSpeedHalf - Train.EntrySpeed) * (double(ElapsedDeltaT) / double(FirstHalfTimeDeltaT)));
14670  }
14671 
14672  else if((Train.BrakeRate <= 0.01) && (Train.ExitSpeedFull > (Train.ExitSpeedHalf + 0.01)) && !Train.FirstHalfMove)
14673  {
14674  Status = "Accelerating";
14675  CurrSpeed = Train.ExitSpeedHalf +
14676  ((Train.ExitSpeedFull - Train.ExitSpeedHalf) * (double(ElapsedDeltaT - FirstHalfTimeDeltaT) / double(SecondHalfTimeDeltaT)));
14677  }
14678 
14679  else if((Train.BrakeRate <= 0.01) && (Train.ExitSpeedFull <= Train.ExitSpeedHalf) && !Train.FirstHalfMove)
14680  {
14681  if(Train.PowerAtRail < 1)
14682  {
14683  if(Train.TrainFailed)
14684  {
14685  Status = "Coasting - train failed";
14686  }
14687  else
14688  {
14689  Status = "Coasting - no power";
14690  }
14691  CurrSpeed = Train.ExitSpeedFull;
14692  }
14693  else
14694  {
14695  Status = "Constant speed";
14696  CurrSpeed = Train.ExitSpeedFull;
14697  }
14698  }
14699 
14700  else // No braking, first half move, ExitSpeedHalf <= EntrySpeed
14701  {
14702  if(Train.PowerAtRail < 1) // as designed there is no way a vehicle can coast without having failed
14703  {
14704  if(Train.TrainFailed)
14705  {
14706  Status = "Coasting - train failed";
14707  }
14708  else
14709  {
14710  Status = "Coasting - no power";
14711  }
14712  CurrSpeed = Train.ExitSpeedHalf;
14713  }
14714  else
14715  {
14716  Status = "Constant speed";
14717  CurrSpeed = Train.ExitSpeedHalf;
14718  }
14719  }
14720  if(Train.TimetableFinished)
14721  {
14722  if(Train.TrainMode == Signaller)
14723  NextStopStr = "At signaller's discretion";
14724  else
14725  NextStopStr = "None";
14726  }
14727  else
14728  NextStopStr = Train.FloatingLabelNextString(0, Train.ActionVectorEntryPtr);
14729  if(Train.TrainMode == Signaller)
14730  {
14731  SpecialStr = "Train under signaller control" + AnsiString('\n');
14732  }
14733  else if(Train.BeingCalledOn && !Train.StoppedAtLocation)
14734  {
14735  SpecialStr = "Restricted speed - being called on" + AnsiString('\n');
14736  }
14737 
14738  double RemTimeHalf = 86400.0 * double(Train.ExitTimeHalf - TrainController->TTClockTime);
14739  if(RemTimeHalf < 0)
14740  RemTimeHalf = 0;
14741  double RemTimeFull = 86400.0 * double(Train.ExitTimeFull - TrainController->TTClockTime);
14742  if(RemTimeFull < 0)
14743  RemTimeFull = 0;
14744  if(RemTimeHalf > 0)
14745  TimeLeft = RemTimeHalf;
14746  else
14747  TimeLeft = RemTimeFull;
14748  TimeToNextMovementStr = "Time to next movement (sec) = " + TimeLeftStr.FormatFloat(FormatOneDPStr, TimeLeft);
14749  if(Train.Stopped())
14750  TimeToNextMovementStr = "";
14751  if(Train.Stopped())
14752  {
14753  TrainStatusFloat = HeadCode + ": " + Train.TrainDataEntryPtr->Description + ServiceReferenceInfo + '\n' + "Maximum train speed " +
14754  MaxSpeedStr + "km/h; Power " + PowerStr + "kW" + '\n' + "Mass " + MassStr + "Te; Brakes " + MaxBrakeStr + "Te" + '\n' + SpecialStr +
14755  Status + '\n' + "Next: " + NextStopStr;
14756  }
14757  else
14758  {
14759  TrainStatusFloat = HeadCode + ": " + Train.TrainDataEntryPtr->Description + ServiceReferenceInfo + '\n' + "Maximum train speed " +
14760  MaxSpeedStr + "km/h; Power " + PowerStr + "kW" + '\n' + "Mass " + MassStr + "Te; Brakes " + MaxBrakeStr + "Te" + '\n' + SpecialStr +
14761  Status + ": " + CurrSpeedStr.FormatFloat(FormatNoDPStr, CurrSpeed) + "km/h" + '\n' + "Next: " + NextStopStr;
14762  }
14763  }
14764  if(TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")
14765  {
14766  ShowTrainTTFloatFlag = true;
14767  TrainTTFloat = Train.FloatingTimetableString(0, Train.ActionVectorEntryPtr);
14768  }
14769  }
14770 
14771  else if(Track->TrackElementAt(666, VecPos).TrackType == Continuation)
14772  // always give train information if a train present, but if not & either of train status or timetable info
14773  // selected then give next expected train to enter, or 'No trains expected'
14774  {
14775  TrainStatusFloat = "No trains expected";
14776  TrainTTFloat = "No timetable";
14777  float EntrySpeed;
14778  int LineSpeedLimit = Track->TrackElementAt(906, VecPos).SpeedLimit01; // speed only in 01 as a continuation
14779  if(TrainStatusInfoOnOffMenuItem->Caption == "Hide Status")
14780  ShowTrainStatusFloatFlag = true;
14781  if(TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")
14782  ShowTrainTTFloatFlag = true;
14784  {
14787  {
14788  while((CTEIt != TrainController->ContinuationTrainExpectationMultiMap.end()) && ((CTEIt->second.VectorPosition != VecPos) ||
14789  (CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry != NotStarted)))
14790  {
14791  CTEIt++;
14792  }
14794  {
14795  TTrainDataEntry *TTDEPtr = CTEIt->second.TrainDataEntryPtr;
14796  AnsiString ServiceReferenceInfo = "";
14797  // Repeat information
14798  if(TTDEPtr->NumberOfTrains > 1) // Service reference information
14799  {
14800  if(CTEIt->second.RepeatNumber == 0)
14801  {
14802  if(CTEIt->second.HeadCode != TTDEPtr->ServiceReference)
14803  ServiceReferenceInfo = "\nFirst service of ref. " + TTDEPtr->ServiceReference;
14804  else
14805  ServiceReferenceInfo = "\nFirst service";
14806  }
14807  else if(CTEIt->second.HeadCode == TTDEPtr->ServiceReference)
14808  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(CTEIt->second.RepeatNumber);
14809  else
14810  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(CTEIt->second.RepeatNumber) + " of ref. " +
14811  TTDEPtr->ServiceReference;
14812  }
14813  else
14814  {
14815  if(CTEIt->second.HeadCode != TTDEPtr->ServiceReference)
14816  ServiceReferenceInfo = "\nService reference " + TTDEPtr->ServiceReference;
14817  }
14818  if(TTDEPtr->ActionVector.at(0).SignallerControl) // entry at 0 is the start entry
14819  {
14820  SpecialStr = "\nTrain under signaller control";
14821  EntrySpeed = TTDEPtr->SignallerSpeed;
14822  if(EntrySpeed > LineSpeedLimit)
14823  EntrySpeed = LineSpeedLimit;
14824  }
14825  else
14826  {
14827  EntrySpeed = TTDEPtr->StartSpeed;
14828  if(EntrySpeed > LineSpeedLimit)
14829  EntrySpeed = LineSpeedLimit;
14830  }
14831  if((CTEIt->first + TDateTime(1.0 / 1440)) < TrainController->TTClockTime) // has to be at least 1 min late to show as late
14832  {
14833  TDateTime TempTime = CTEIt->first;
14834 // need this because CTEIt points to a const object and shouldn't use FormatString on a const object
14835  TrainStatusFloat = CTEIt->second.HeadCode + ": " + CTEIt->second.Description + ServiceReferenceInfo + "\nEntry speed " +
14836  AnsiString::FormatFloat(FormatNoDPStr, EntrySpeed) + "km/h" + SpecialStr + "\nDelayed, was due at " +
14837  Utilities->Format96HHMM(TempTime);
14838  }
14839  else
14840  {
14841  TDateTime TempTime = CTEIt->first;
14842 // need this because CTEIt points to a const object and shouldn't use FormatString on a const object
14843  TrainStatusFloat = CTEIt->second.HeadCode + ": " + CTEIt->second.Description + ServiceReferenceInfo + "\nEntry speed " +
14844  AnsiString::FormatFloat(FormatNoDPStr, EntrySpeed) + "km/h" + SpecialStr + "\nExpected at " +
14845  Utilities->Format96HHMM(TempTime);
14846  }
14847  if(TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")
14848  {
14849  if(!TTDEPtr->ActionVector.at(0).SignallerControl) // if signaller control there's no timetable & SpecialStr covers this
14850  {
14851  TrainTTFloat = TrainController->ContinuationEntryFloatingTTString(0, TTDEPtr, CTEIt->second.RepeatNumber,
14852  CTEIt->second.IncrementalMinutes, CTEIt->second.IncrementalDigits);
14853  }
14854  }
14855  }
14856  }
14857  }
14858  }
14859  }
14860  }
14861 
14862 // end of TrainFloat section
14863  AnsiString Caption;
14864 
14865  if(!ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14866  {
14867  FloatingPanel->Visible = false;
14868  Utilities->CallLogPop(1485);
14869  return; // return with label invisible
14870  }
14871  else if(ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14872  {
14873  Caption = TrackFloat;
14874  }
14875  else if(!ShowTrackFloatFlag && ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14876  {
14877  Caption = TrainStatusFloat;
14878  }
14879  else if(ShowTrackFloatFlag && ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14880  {
14881  Caption = TrainStatusFloat + '\n' + '\n' + TrackFloat;
14882  }
14883  else if(!ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14884  {
14885  if(TrainStatusFloat == "No trains expected")
14886  Caption = TrainStatusFloat;
14887  else
14888  Caption = TrainTTFloat;
14889  }
14890  else if(ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14891  {
14892  if(TrainStatusFloat == "No trains expected")
14893  Caption = TrainStatusFloat + '\n' + '\n' + TrackFloat;
14894  else
14895  Caption = TrainTTFloat + '\n' + '\n' + TrackFloat;
14896  }
14897  else if(!ShowTrackFloatFlag && ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14898  {
14899  if(TrainStatusFloat == "No trains expected")
14900  Caption = TrainStatusFloat;
14901  else
14902  Caption = TrainStatusFloat + '\n' + '\n' + TrainTTFloat;
14903  }
14904  else if(ShowTrackFloatFlag && ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14905  {
14906  if(TrainStatusFloat == "No trains expected")
14907  Caption = TrainStatusFloat + '\n' + '\n' + TrackFloat;
14908  else
14909  Caption = TrainStatusFloat + '\n' + '\n' + TrainTTFloat + '\n' + '\n' + TrackFloat;
14910  }
14911 
14912  int Left = ScreenX + MainScreen->Left + 16; // so lhs of window is one element to the right of the mouse pos
14913 
14914 // this offset is because window position is relative to the interface form, whereas ScreenX & Y are relative to the MainScreen, which is
14915 // offset 32 to the right and 95 down from the interface form
14916  if((Left + FloatingPanel->Width) > MainScreen->Left + MainScreen->Width)
14917  Left = ScreenX - FloatingPanel->Width + 16; // so rhs of window is one element to the left of the mouse pos (+32 would be at mouse pos)
14918  int Top = ScreenY + MainScreen->Top + 16; // so top of window is one element below the mouse pos (ScreenY + MainScreen->Top would be at mouse pos)
14919 
14920  if((Top + FloatingPanel->Height) > MainScreen->Top + MainScreen->Height)
14921  {
14922  Top = ScreenY - FloatingPanel->Height + 79; // so bottom of window is one element above the mouse pos (95 would be at mouse pos)
14923  // but, top may now be off the top of the screen, if so position at the top of the screen, as always need to see the top, if have to
14924  // lose something then it's best to be from the bottom
14925  if(Top < 30) // use 30 instead of MainScreen->Top [95] as top can go off MainScreen providing it doesn't reach the information panel, as that would
14926  // obscure the window
14927  {
14928  Top = 30;
14929  }
14930  }
14931  if((Left != FloatingPanel->Left) || (Top != FloatingPanel->Top))
14932  {
14933  FloatingPanel->Visible = false; // so doesn't flicker when reposition
14934  FloatingPanel->Left = Left;
14935  FloatingPanel->Top = Top;
14936  Utilities->CallLogPop(1917);
14937  return;
14938  }
14939 
14940  FloatingLabel->Caption = Caption;
14941  FloatingPanel->Visible = true;
14942  FloatingPanel->BringToFront();
14943  Utilities->CallLogPop(746);
14944 }
14945 
14946 // ---------------------------------------------------------------------------
14947 
14948 void TInterface::FlashingGraphics(int Caller, TDateTime Now)
14949  // following section checks to see if GapFlashFlag set & flashes the Gap graphics if so
14950  // Gap flashing is cancelled on any mousedown event
14951 
14952  // deal with flashing GapFlash graphics (only in basic mode so no need to check for trains)
14953 {
14954  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",FlashingGraphics");
14956  {
14957  if(WarningFlash)
14958  {
14959  Track->GapFlashGreen->PlotOverlay(4, Display); // only plotted if PlotOverlay reset
14961  }
14962  else
14963  {
14964  Track->GapFlashGreen->PlotOriginal(17, Display); // only plotted if PlotOverlay set
14966  }
14967  }
14968 
14970  {
14971  if(WarningFlash)
14972  {
14977  Display->Update();
14978  }
14979  else
14980  {
14985  Display->Update();
14986  }
14987  }
14988 
14989 // deal with other flashing graphics
14991  {
14992  if((Now - RouteFlashStartTime) < TDateTime(RouteFlashDuration / 86400))
14993  {
14994  // cancel if train is moving & arrives on any part of flashing route
14996  {
14997  Track->RouteFlashFlag = false;
14999  ClearandRebuildRailway(18); // because using ConstructRoute->RouteFlash.PlotOriginal() can plot wrong point fillet as well as
15000  // original (if proposed route would change point). With this can dispense with ConstructRoute->RouteFlash.PlotOriginal()
15001  Utilities->CallLogPop(75);
15002  return;
15003  }
15004 
15005  InfoPanel->Visible = true;
15006  if(Level2OperMode == PreStart)
15007  InfoPanel->Caption = "PRE-START: Route setting in progress";
15008  else
15009  InfoPanel->Caption = "OPERATING: Route setting in progress";
15010  if(WarningFlash)
15011  {
15013  }
15014  else
15015  {
15017  }
15018  }
15019  else
15020  {
15021 // ConstructRoute->RouteFlash.PlotOriginal(); don't need with clearand....
15022 // stop clock while converting route as can take several seconds
15023  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
15025  if(PreferredRouteFlag)
15027  else
15029  ConstructRoute->ClearRoute(); // clear it immediately after use so as not to clutter the errorlog
15030  TrainController->BaseTime = TDateTime::CurrentDateTime();
15032  Track->RouteFlashFlag = false;
15034  ClearandRebuildRailway(19); // if drop this ensure replot trains after replot routes else route will overwrite a train
15035  }
15036  }
15037 
15038  if(Track->RouteFlashFlag && Display->ZoomOutFlag) // must have entered RouteFlash from normal screen so button states stored
15039  // dropped ZoomOutButton when route or point flashing, but leave this section in in case need to reinstate
15040  // no need to call Clearand... as that is called when revert to normal mode
15041  {
15042  if((Now - RouteFlashStartTime) >= TDateTime(RouteFlashDuration / 86400))
15043  {
15044  Track->RouteFlashFlag = false;
15045  if(PreferredRouteFlag)
15046  {
15048  }
15049  else
15050  {
15052  }
15053  ConstructRoute->ClearRoute(); // clear it immediately after use so as not to clutter the errorlog
15054  }
15055  }
15056 
15058  {
15059  if((Now - PointFlashStartTime) < TDateTime((PointsFlashDuration) / 86400))
15060  {
15061  // cancel if train is present on or enters a flashing point, either selected or diverging
15063  {
15065  Track->PointFlashFlag = false;
15067  Utilities->CallLogPop(76);
15068  return;
15069  }
15071  {
15073  Track->PointFlashFlag = false;
15075  Utilities->CallLogPop(77);
15076  return;
15077  }
15078 
15079  if(WarningFlash)
15080  {
15083  }
15084  else
15085  {
15087  }
15088  }
15089  else
15090  {
15095  {
15099  }
15101  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
15102  Track->PointFlashFlag = false;
15104  }
15105  }
15106 
15108  // dropped ZoomOutButton when point flashing but leave this section in in case need to reinstate
15109  {
15110  if((Now - PointFlashStartTime) < TDateTime((PointsFlashDuration) / 86400))
15111  {
15115  {
15118  }
15119  Track->PointFlashFlag = false;
15121  }
15122  }
15123 // deal with level crossings
15124  if(!Track->ChangingLCVector.empty() && (Level2OperMode != Paused))
15125  {
15126  int H;
15127  int V;
15128 
15129  for(unsigned int x = 0; x < Track->ChangingLCVector.size(); x++)
15130  {
15131  bool Manual = false;
15132  if(Track->ChangingLCVector.at(x).ConsecSignals == 2) //manual
15133  {
15134  Manual = true;
15135  }
15136  H = Track->ChangingLCVector.at(x).HLoc;
15137  V = Track->ChangingLCVector.at(x).VLoc;
15138  if((Now - Track->ChangingLCVector.at(x).StartTime) < TDateTime((Track->ChangingLCVector.at(x).ChangeDuration) / 86400))
15139  // still flashing
15140  {
15141  if(WarningFlash)
15142  {
15143  if(Track->ChangingLCVector.at(x).BarrierState == TTrack::Raising) // closing to trains
15144  {
15145  Track->PlotRaisedLinkedLevelCrossingBarriers(1, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V, Display); //always plots red when raising
15146  }
15147  else
15148  {
15149  Track->PlotLoweredLinkedLevelCrossingBarriers(0, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V,
15150  Track->ChangingLCVector.at(x).ConsecSignals, Display, Manual);
15151  }
15152  }
15153  else
15154  {
15155  Track->PlotLCBaseElementsOnly(2, Track->ChangingLCVector.at(x).BarrierState, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V,
15156  Track->ChangingLCVector.at(x).ConsecSignals, Display);
15157  }
15158  }
15159  else
15160  // flashing period finished
15161  {
15162  if(Track->ChangingLCVector.at(x).BarrierState == TTrack::Raising)
15163  {
15164  Track->PlotRaisedLinkedLevelCrossingBarriers(2, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V, Display); //always plot red when fully raised
15165  Track->SetLinkedLevelCrossingBarrierAttributes(4, H, V, 0); // only set attr to 0 when fully raised
15166  // attributes set to 2 when changing state, now reset to 0, no other actions needed
15167  }
15168  else
15169  // barriers lowering
15170  {
15171  Track->PlotLoweredLinkedLevelCrossingBarriers(1, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V,
15172  Track->ChangingLCVector.at(x).ConsecSignals, Display, Manual);
15173  Track->SetLinkedLevelCrossingBarrierAttributes(5, H, V, 1); // only set attr to 1 when fully lowered
15174  bool FoundFlag;
15175  int TVPos = Track->GetVectorPositionFromTrackMap(46, H, V, FoundFlag);
15176  if(!FoundFlag)
15177  {
15178  throw Exception("Failed to find a route at LC position HLoc = " + (AnsiString)H + " VLoc = " + (AnsiString)V);
15179  }
15180  int RouteNumber;
15181  AllRoutes->GetRouteTypeAndNumber(24, TVPos, 0, RouteNumber); // use 0 for LinkPos, could be 1 or 0 as only a single track element
15182  // don't need returned value of RouteType
15183  if(RouteNumber > -1) // if train crashed then there won't be a routenumber
15184  {
15185  AllRoutes->GetFixedRouteAt(196, RouteNumber).SetRouteSignals(8);
15186  }
15187  }
15188  }
15189  }
15190  for(int x = Track->ChangingLCVector.size() - 1; x >= 0; x--)
15191  // now transfer lowering barrier object from the ChangingLCVector to the BarriersDownVector if lowering, reset the start timer (to time the barrier down period)
15192  // and for either raising or lowering erase the object from the ChangingLCVector
15193  {
15194  if(!Track->IsLCBarrierFlashingAtHV(0, Track->ChangingLCVector.at(x).HLoc, Track->ChangingLCVector.at(x).VLoc))
15195  {
15196  if(Track->ChangingLCVector.at(x).BarrierState == TTrack::Lowering)
15197  {
15198  Track->ChangingLCVector.at(x).StartTime = TrainController->TTClockTime;
15199  Track->ChangingLCVector.at(x).BarrierState = TTrack::Down;
15200  Track->BarriersDownVector.push_back(Track->ChangingLCVector.at(x));
15201  }
15202  Track->ChangingLCVector.erase(Track->ChangingLCVector.begin() + x);
15203  }
15204  }
15205  }
15206  Utilities->CallLogPop(747);
15207 }
15208 
15209 // ---------------------------------------------------------------------------
15210 
15212  // set boundary, Home, NewHome, ZoomOut, CallingOn buttons & menu items as appropriate
15213 {
15214  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetSaveMenuAndButtons");
15215 
15216 // set save railway buttons
15217  bool SaveRailwayButtonsFlag = true;
15218 
15219  SaveRailwayTBPButton->Visible = true;
15220  SaveRailwayPDPButton->Visible = true;
15221  SaveSessionButton->Visible = true;
15222  if(Level1Mode == OperMode)
15223  {
15225  {
15226  SaveRailwayButtonsFlag = false;
15227  }
15228  // set PresetAutoSigRoutesButton enabled or not
15229  // enable if PreStart & no routes set
15230  if((Level2OperMode == PreStart) && (AllRoutes->AllRoutesVector.empty()))
15231  {
15232  PresetAutoSigRoutesButton->Enabled = true;
15233  }
15234  else
15235  {
15236  PresetAutoSigRoutesButton->Enabled = false;
15237  }
15238  }
15239  else
15240  {
15242  {
15243  SaveRailwayButtonsFlag = false;
15244  }
15245  else if(SavedFileName != "")
15246  {
15247  if((SavedFileName[SavedFileName.Length()] == 'y') || (SavedFileName[SavedFileName.Length()] == 'Y')) // 'rly' file
15248  {
15249  if(!(Track->IsReadyForOperation()))
15250  {
15251  SaveRailwayButtonsFlag = false; // can't save under its old name as not now a .rly file
15252  }
15253  }
15254  }
15255  }
15256  if(SaveRailwayButtonsFlag && (Level1Mode == BaseMode))
15257  {
15258  SaveRailwayBaseModeButton->Visible = true;
15259  }
15260  else
15261  {
15262  SaveRailwayBaseModeButton->Visible = false;
15263  }
15264  SaveRailwayTBPButton->Enabled = SaveRailwayButtonsFlag;
15265  SaveRailwayPDPButton->Enabled = SaveRailwayButtonsFlag;
15266  SaveRailwayBaseModeButton->Enabled = SaveRailwayButtonsFlag;
15267  SaveSessionButton->Enabled = SaveRailwayButtonsFlag;
15268 
15269 // set formatted timetable menu item
15270  if(TimetableTitle == "")
15271  {
15272  ExportTTMenuItem->Enabled = false;
15273  }
15274  else
15275  {
15276  ExportTTMenuItem->Enabled = true;
15277  }
15278 
15279 // set info menu items
15281  {
15282  FloatingInfoMenu->Enabled = false;
15283  TrackInfoMenuItem->Enabled = false;
15284  TrainInfoMenuItem->Enabled = false;
15285  }
15286  else
15287  {
15288  FloatingInfoMenu->Enabled = true;
15289  TrackInfoMenuItem->Enabled = true;
15290  if(Level1Mode == OperMode)
15291  {
15292  TrainInfoMenuItem->Enabled = true;
15293  }
15294  else
15295  {
15296  TrainInfoMenuItem->Enabled = false;
15297  }
15298  }
15299 
15300 // set all bar CallingOnButton operational to begin with - no, causes flickering of button graphics,
15301 // work on internal flags & then set buttons according to final flag values, then graphic won't change unless
15302 // there has been a legitimate change of state since the last access
15303 
15304  bool ZoomFlag = true, HomeFlag = true, NewHomeFlag = true, ScreenLeftFlag = true, ScreenRightFlag = true, ScreenUpFlag = true, ScreenDownFlag = true,
15305  TrackBuildPanelEnabledFlag = true, PrefDirPanelEnabledFlag = true, OperatingPanelEnabledFlag = true, TimetablePanelEnabledFlag = true;
15306 
15307  AnsiString TrackBuildPanelLabelCaptionStr = "Build/modify";
15308  AnsiString PrefDirPanelLabelCaptionStr = "Preferred direction selection";
15309  AnsiString OperatingPanelLabelCaptionStr = "Operation";
15310  AnsiString TimetablePanelLabelCaptionStr = "Timetable editor";
15311 
15312  if(!Display->ZoomOutFlag)
15313  { // prevent if half a screen or less visible (width = 60, height = 36) [Note HLocMin & Max 1 greater than extreme element]
15315  ScreenLeftFlag = false; // 60 - 30
15317  ScreenRightFlag = false; // 60 - (60 - 30)
15319  ScreenUpFlag = false; // 36 - 18
15321  ScreenDownFlag = false; // 36 - (36 - 18)
15322  }
15323  else
15324  { // prevent if less than a quarter of a screen visible (width = 240, height = 144)
15326  ScreenLeftFlag = false; // 240 - 60
15328  ScreenRightFlag = false; // 240 - (240 - 60)
15330  ScreenUpFlag = false; // 144 - 36
15332  ScreenDownFlag = false; // 144 - (144 - 36)
15333  }
15335  {
15336  ZoomFlag = false;
15337  HomeFlag = false;
15338  NewHomeFlag = false;
15339  ScreenLeftFlag = false;
15340  ScreenRightFlag = false;
15341  ScreenUpFlag = false;
15342  ScreenDownFlag = false;
15343  }
15344 
15345  if(Display->ZoomOutFlag)
15346  {
15347 // NewHomeFlag = false;
15348  TrackBuildPanelEnabledFlag = false;
15349  TrackBuildPanelLabelCaptionStr = "Disabled";
15350  PrefDirPanelEnabledFlag = false;
15351  PrefDirPanelLabelCaptionStr = "Disabled";
15352  OperatingPanelEnabledFlag = false;
15353  OperatingPanelLabelCaptionStr = "Disabled";
15354  TimetablePanelEnabledFlag = false;
15355  TimetablePanelLabelCaptionStr = "Disabled";
15356  }
15357 
15358  if(Level1Mode == OperMode)
15359  {
15360  if(Track->RouteFlashFlag || Track->PointFlashFlag || TTClockAdjPanel->Visible == true || TTClockAdjustWarningPanel->Visible == true) //TTClockAdjPanel added for v2.4.2 to keep it disabled after Clock2Stopped dropped
15361  {
15362  MTBFEditBox->Enabled = false;
15363  OperatingPanelEnabledFlag = false;
15364  OperatingPanelLabelCaptionStr = "Disabled";
15365  ZoomFlag = false;
15366  HomeFlag = false;
15367  NewHomeFlag = false;
15368  ScreenLeftFlag = false;
15369  ScreenRightFlag = false;
15370  ScreenUpFlag = false;
15371  ScreenDownFlag = false;
15372  SaveOperatingImageMenuItem->Enabled = false;
15373  }
15374  else
15375  {
15376  MTBFEditBox->Enabled = true;
15377  SaveOperatingImageMenuItem->Enabled = true;
15378  }
15379  }
15380 
15381  if(LocationNameTextBox->Visible)
15382  {
15383  ZoomFlag = false;
15384  HomeFlag = false;
15385  NewHomeFlag = false;
15386  ScreenLeftFlag = false;
15387  ScreenRightFlag = false;
15388  ScreenUpFlag = false;
15389  ScreenDownFlag = false;
15390  }
15391 
15392  if(TextBox->Visible) // added at v1.3.0 to prevent screen moving when movement keys pressed during text entry
15393  {
15394  ZoomFlag = false;
15395  HomeFlag = false;
15396  NewHomeFlag = false;
15397  ScreenLeftFlag = false;
15398  ScreenRightFlag = false;
15399  ScreenUpFlag = false;
15400  ScreenDownFlag = false;
15401  }
15402 
15403  if((Level1Mode == TimetableMode) && (TimetableEditPanel->Visible))
15404  // added at v1.3.0 to prevent screen moving when movement keys pressed during timetable compilation (allowed if TT hidden)
15405  {
15406  ZoomFlag = false;
15407  HomeFlag = false;
15408  NewHomeFlag = false;
15409  ScreenLeftFlag = false;
15410  ScreenRightFlag = false;
15411  ScreenUpFlag = false;
15412  ScreenDownFlag = false;
15413  }
15414 
15417  {
15418  ZoomFlag = false;
15419  }
15420 
15421  if(ZoomFlag)
15422  ZoomButton->Enabled = true;
15423  else
15424  ZoomButton->Enabled = false;
15425  if(HomeFlag)
15426  HomeButton->Enabled = true;
15427  else
15428  HomeButton->Enabled = false;
15429  if(NewHomeFlag)
15430  NewHomeButton->Enabled = true;
15431  else
15432  NewHomeButton->Enabled = false;
15433  if(ScreenLeftFlag)
15434  ScreenLeftButton->Enabled = true;
15435  else
15436  ScreenLeftButton->Enabled = false;
15437  if(ScreenRightFlag)
15438  ScreenRightButton->Enabled = true;
15439  else
15440  ScreenRightButton->Enabled = false;
15441  if(ScreenUpFlag)
15442  ScreenUpButton->Enabled = true;
15443  else
15444  ScreenUpButton->Enabled = false;
15445  if(ScreenDownFlag)
15446  ScreenDownButton->Enabled = true;
15447  else
15448  ScreenDownButton->Enabled = false;
15449  if(OperatingPanelEnabledFlag)
15450  OperatingPanel->Enabled = true;
15451  else
15452  OperatingPanel->Enabled = false;
15453  if(TrackBuildPanelEnabledFlag)
15454  TrackBuildPanel->Enabled = true;
15455  else
15456  TrackBuildPanel->Enabled = false;
15457  if(PrefDirPanelEnabledFlag)
15458  PrefDirPanel->Enabled = true;
15459  else
15460  PrefDirPanel->Enabled = false;
15461  if(TimetablePanelEnabledFlag)
15462  TimetablePanel->Enabled = true;
15463  else
15464  TimetablePanel->Enabled = false;
15465  TrackBuildPanelLabel->Caption = TrackBuildPanelLabelCaptionStr;
15466  PrefDirPanelLabel->Caption = PrefDirPanelLabelCaptionStr;
15467  OperatingPanelLabel->Caption = OperatingPanelLabelCaptionStr;
15468  TimetablePanelLabel->Caption = TimetablePanelLabelCaptionStr;
15469 
15470 // check if any CallingOnFlags set & set button accordingly
15471  if(Display->ZoomOutFlag)
15472  {
15473  CallingOnButton->Enabled = false;
15474  CallingOnButton->Down = false;
15475  }
15476  else
15477  {
15478  if(Level2OperMode == Operating)
15479  {
15480  bool CallOnValid = false;
15481  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
15482  {
15484  {
15485  CallingOnButton->Enabled = true;
15486  CallOnValid = true;
15487  }
15488  }
15489  if(!CallOnValid)
15490  {
15491  CallingOnButton->Enabled = false;
15492  CallingOnButton->Down = false;
15493  }
15494  }
15495  else
15496  {
15497  CallingOnButton->Enabled = false;
15498  CallingOnButton->Down = false;
15499  }
15500  }
15501  Utilities->CallLogPop(970);
15502 }
15503 
15504 // ---------------------------------------------------------------------------
15505 
15506 void TInterface::ErrorLog(int Caller, AnsiString Message)
15507 {
15508 // create an error file for diagnostic purposes called on detection of a runtime error
15509 
15510 // Note: For faults in ClockTimer2, after the catch block in ClockTimer2 which calls this function, execution continues from where
15511 // ClockTimer2 was called, so the Utilities->Clock2Stopped flag is cleared and the whole sequence repeats itself, including the fault, until
15512 // the user presses the Exit button. Note also that Utilities->CallLogPop, called when ClockTimer (not ClockTimer2) returns, pops the error
15513 // message off the back of the Utilities->CallLog, not the ClockTimer call. Hence entries keep stacking up, including the push_front entry
15514 // but not the push_back error entry, and when finally printed there is a whole series of entries for the one fault, the number
15515 // depending on the time taken to press Exit.
15516 // Hence introduce an ErrorLogCalledFlag, set to true on first call, and preventing further calls thereafter.
15517 
15518  if(ErrorLogCalledFlag)
15519  return;
15520 
15521  ErrorLogCalledFlag = true;
15522  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + "," + Message);
15523  Utilities->CallLog.push_front("Version: " + ProgramVersion + "; Time and date: " + Utilities->DateTimeStamp());
15524  SaveErrorFile();
15525  if((TempTTFileName != "") && FileExists(TempTTFileName))
15526  {
15527  DeleteFile(TempTTFileName);
15528  }
15529  Display->GetImage()->Visible = false;
15530  PerformancePanel->Visible = false;
15531  OperatorActionPanel->Visible = false; // new v2.2.0
15532  TrackBuildPanel->Visible = false;
15533  TrackElementPanel->Visible = false;
15534  LocationNameTextBox->Visible = false;
15535  TextBox->Visible = false;
15536  TrackLengthPanel->Visible = false;
15537  InfoPanel->Visible = false;
15538  PrefDirPanel->Visible = false;
15539  TimetablePanel->Visible = false;
15540  TimetableEditPanel->Visible = false;
15541  TrainController->TTEditPanelVisible = false; //added at v2.6.0 for two location message
15542  OperatingPanel->Visible = false;
15543  FloatingPanel->Visible = false;
15544  ModeMenu->Enabled = false;
15545  SigImagePanel->Visible = false; // new at v2.3.0
15546  FileMenu->Enabled = false;
15547  EditMenu->Enabled = false;
15548  FloatingInfoMenu->Enabled = false;
15549  HelpMenu->Enabled = false;
15550 // SaveHeaderMenu1->Enabled = false;
15551  ScreenLeftButton->Visible = false;
15552  ScreenRightButton->Visible = false;
15553  ScreenUpButton->Visible = false;
15554  ScreenDownButton->Visible = false;
15555  HomeButton->Visible = false;
15556  NewHomeButton->Visible = false;
15557  ZoomButton->Visible = false;
15558  PrefDirKey->Visible = false;
15559  DistanceKey->Visible = false;
15560  OutputLog1->Caption = "";
15561  OutputLog2->Caption = "";
15562  OutputLog3->Caption = "";
15563  OutputLog4->Caption = "";
15564  OutputLog5->Caption = "";
15565  OutputLog6->Caption = "";
15566  OutputLog7->Caption = "";
15567  OutputLog8->Caption = "";
15568  OutputLog9->Caption = "";
15569  OutputLog10->Caption = "";
15570  if(Caller == 113)
15571  {
15572  ErrorMessageStoreImage->Visible = true;
15573  }
15574  else
15575  {
15576  ErrorMessage->Visible = true;
15577  }
15578  ErrorButton->Visible = true;
15579  Screen->Cursor = TCursor(-2); // Arrow; - in case was an hourglass
15580 // No need for Utilities->CallLogPop as the call log deque has already been written to file & the next action
15581 // is to close the program when the exit button is pressed
15582 }
15583 
15584 // ---------------------------------------------------------------------------
15585 
15587  // not used from v2.2.0 as now allow floating panel & label to overlie performance panel
15588 {
15589  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",IsPerformancePanelObscuringFloatingLabel");
15590  if(FloatingPanel->Visible == false)
15591  {
15592  Utilities->CallLogPop(1205);
15593  return false;
15594  }
15595 // pptop >= flbot, ppbot <= fltop, ppleft >= flright, ppright <= flleft
15596  if((PerformancePanel->Top >= (FloatingPanel->Top + FloatingPanel->Height)) || ((PerformancePanel->Top + PerformancePanel->Height) <= FloatingPanel->Top) ||
15597  (PerformancePanel->Left >= (FloatingPanel->Left + FloatingPanel->Width)) || ((PerformancePanel->Left + PerformancePanel->Width) <= FloatingPanel->Left))
15598  {
15599  Utilities->CallLogPop(1206);
15600  return false;
15601  }
15602  else
15603  {
15604  Utilities->CallLogPop(1207);
15605  return true;
15606  }
15607 }
15608 // ---------------------------------------------------------------------------
15609 
15610 void TInterface::SetCaption(int Caller)
15611 {
15612 /*
15613  NamedRailway; RlyFile; NamedTimetable
15614  n x x "New railway under development";
15615  y n x RailwayTitle + ": under development";
15616  y y n RailwayTitle + ": no timetable loaded";
15617  y y y RailwayTitle + ", " + TimetableTitle;
15618 */
15619 
15620  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetCaption");
15621  if(RailwayTitle == "")
15622  Caption = "Railway: New railway under development";
15623  else if(!RlyFile)
15624  Caption = "Railway: " + RailwayTitle + " under development";
15625 // else if(TimetableTitle == "") Caption = "Railway: " + RailwayTitle + "; Timetable: none loaded";
15626  else if(TimetableTitle == "")
15627  Caption = "Railway: " + RailwayTitle; // changed at v2.1.0, no need to mention TT if none loaded
15628  else
15629  Caption = "Railway: " + RailwayTitle + "; Timetable: " + TimetableTitle;
15630  Utilities->CallLogPop(1208);
15631 }
15632 
15633 // ---------------------------------------------------------------------------
15634 
15635 void TInterface::ResetAll(int Caller)
15636 {
15637  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ResetAll");
15638  LastNonCtrlOrShiftKeyDown = -1; // added at v2.4.2 to no key down
15640  Track->GapFlashRedPosition = -1;
15641  Track->GapFlashFlag = false;
15642  Track->RouteFlashFlag = false;
15643  Track->PointFlashFlag = false;
15645  AutoSigsFlag = false;
15646  PreventGapOffsetResetting = false;
15647 
15648  Utilities->Clock2Stopped = false;
15649  TTClockSpeed = 1;
15650  TTClockSpeedLabel->Caption = "x1";
15651  Track->SetTrackFinished(false);
15653  CurrentSpeedButton = 0; // not assigned yet
15655  StartX = 0;
15656  StartY = 0;
15657  mbLeftDown = false;
15659  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision1");
15661  SigAspectButton->Glyph->LoadFromResourceName(0, "FourAspect");
15663  WarningFlashCount = 0;
15664 
15665  Level1Mode = BaseMode;
15666  SetLevel1Mode(26);
15667  RouteMode = None;
15668  PreferredRoute = true;
15669  ConsecSignalsRoute = true;
15670  DevelopmentPanel->Visible = false;
15671 
15672  MainScreen->Canvas->CopyMode = cmSrcCopy;
15673  FloatingPanel->Visible = false;
15674  OverallDistance = 0;
15675  OverallSpeedLimit = -1;
15676  AllRoutes->RouteTruncateFlag = false;
15677  CallingOnButton->Down = false;
15678  Display->ZoomOutFlag = false;
15679  ScreenGridFlag = false;
15680  InfoCaptionStore = "";
15681  ErrorLogCalledFlag = false;
15682  ErrorMessage->Visible = false;
15683  ErrorMessageStoreImage->Visible = false;
15684  TempCursorSet = false;
15685  TempCursor = TCursor(-2); // Arrow
15686  WholeRailwayMoving = false; // new at v2.1.0
15687 
15688  TrainController->TTClockTime = TDateTime(0); // default setting
15689  TTClockAdjPanel->Visible = false;
15691  ConflictPanel->Visible = false;
15692  SelectedTrainID = -1;
15693  SetTrackBuildImages(11);
15694 // TrackInfoOnOffMenuItem->Caption = "Show"; dropped these here at v1.2.0 so don't reset when load a session file
15695 // TrainStatusInfoOnOffMenuItem->Caption = "Show Status";
15696 // TrainTTInfoOnOffMenuItem->Caption = "Show Timetable";
15697  Track->CalcHLocMinEtc(8);
15698  FileChangedFlag = false;
15699  RlyFile = false;
15700  SaveSessionFlag = false;
15701  LoadSessionFlag = false;
15702  SelectionValid = false;
15703  TimetableChangedFlag = false;
15704  SavedFileName = "";
15705  RailwayTitle = "";
15706  TimetableTitle = "";
15707  SetCaption(1);
15708  CreateEditTTFileName = ""; // set to null to allow a check during error file saving, if not null save the tt being edited to the file
15709  // added for Beta v0.2b
15710  CreateEditTTTitle = ""; // as above
15711  AllRoutes->NextRouteID = 0;
15712  TTrain::NextTrainID = 0; // reset to 0 whenever enter operating mode
15713  TFont *TempFont = new TFont; // if try to alter MainScreen->Canvas->Font directly it won't change the style for some reason
15714 
15715  TempFont->Style.Clear();
15716  TempFont->Name = "MS Sans Serif"; // reset font, else stays set to last displayed text font
15717  TempFont->Size = 10;
15718  TempFont->Color = clB0G0R0;
15719  TempFont->Charset = (TFontCharset)(0);
15720  MainScreen->Canvas->Font->Assign(TempFont);
15721  PerformancePanel->Top = MainScreen->Top + MainScreen->Height - PerformancePanel->Height;
15722  PerformancePanel->Left = MainScreen->Left;
15723  OperatorActionPanel->Top = MainScreen->Top + MainScreen->Height - OperatorActionPanel->Height; // new v2.2.0
15724  OperatorActionPanel->Left = MainScreen->Left + MainScreen->Width - OperatorActionPanel->Width; ; // new v2.2.0
15725  // ScreenRightButton->Left = MainScreen->Width + MainScreen->Left; //Button values changed at v2.1.0 to allow for screen resizing
15726  // ScreenLeftButton->Left = ScreenRightButton->Left;
15727  // ScreenUpButton->Left = ScreenRightButton->Left;
15728  // ScreenDownButton->Left = ScreenRightButton->Left;
15729  // HomeButton->Left = ScreenRightButton->Left;
15730  // NewHomeButton->Left = ScreenRightButton->Left;
15731  // ZoomButton->Left = ScreenRightButton->Left;
15732  DevelopmentPanel->Top = MainScreen->Top + MainScreen->Height - DevelopmentPanel->Height;
15733  DevelopmentPanel->Left = MainScreen->Left + MainScreen->Width - DevelopmentPanel->Width; ; // new v2.2.0
15734 
15735  delete TempFont;
15736  CtrlKey = false;
15737  ShiftKey = false;
15738  Utilities->CallLogPop(1209);
15739 }
15740 
15741 // ---------------------------------------------------------------------------
15742 
15744 {
15745  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetTrackBuildImages,");
15746  if((Level1Mode == OperMode) || RlyFile)
15747  {
15748  TrackLinkedImage->Visible = false;
15749  TrackNotLinkedImage->Visible = false;
15750  GapsSetImage->Visible = false;
15751  GapsNotSetImage->Visible = false;
15752  LocationNamesSetImage->Visible = false;
15753  LocationNamesNotSetImage->Visible = false;
15754  Utilities->CallLogPop(1114);
15755  return;
15756  }
15757  else
15758  {
15759  if(!Track->NoActiveTrack(9))
15760  {
15761  if(Track->IsTrackFinished())
15762  {
15763  TrackLinkedImage->Visible = true;
15764  TrackNotLinkedImage->Visible = false;
15765  }
15766  else
15767  {
15768  TrackNotLinkedImage->Visible = true;
15769  TrackLinkedImage->Visible = false;
15770  }
15771  }
15772  else
15773  {
15774  TrackLinkedImage->Visible = false;
15775  TrackNotLinkedImage->Visible = false;
15776  }
15777 
15778  if(!Track->NoGaps(1))
15779  {
15780  if(Track->GapsUnset(6))
15781  {
15782  GapsNotSetImage->Visible = true;
15783  GapsSetImage->Visible = false;
15784  }
15785  else
15786  {
15787  GapsNotSetImage->Visible = false;
15788  GapsSetImage->Visible = true;
15789  }
15790  }
15791  else
15792  {
15793  GapsNotSetImage->Visible = false;
15794  GapsSetImage->Visible = false;
15795  }
15796 
15798  {
15799  if(Track->LocationsNotNamed(0))
15800  {
15801  LocationNamesSetImage->Visible = false;
15802  LocationNamesNotSetImage->Visible = true;
15803  }
15804  else
15805  {
15806  LocationNamesSetImage->Visible = true;
15807  LocationNamesNotSetImage->Visible = false;
15808  }
15809  }
15810  else
15811  {
15812  LocationNamesSetImage->Visible = false;
15813  LocationNamesNotSetImage->Visible = false;
15814  }
15815  }
15816  Utilities->CallLogPop(1113);
15817 }
15818 
15819 // ---------------------------------------------------------------------------
15820 
15821 void TInterface::ResetChangedFileDataAndCaption(int Caller, bool NonPrefDirChangesMade)
15822 {
15823  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ResetChangedFileDataAndCaption");
15824  FileChangedFlag = true;
15825  if(NonPrefDirChangesMade)
15826  {
15827  if(RlyFile) // i.e. was a Railway file but major changes made so class as a new railway
15828  {
15829  RailwayTitle = "";
15830  TimetableTitle = "";
15831  SavedFileName = "";
15832  RlyFile = false;
15833  }
15834  TimetableTitle = ""; // should have been reset already during user mode change but include here also
15835  SetTrackBuildImages(15);
15836  }
15837  SetCaption(2);
15838  Utilities->CallLogPop(1210);
15839 }
15840 
15841 // ---------------------------------------------------------------------------
15842 
15843 void TInterface::SaveSession(int Caller)
15844 { // ExcessLCDownMins saved as string after ***Interface*** see below
15845  try
15846  {
15847  TrainController->LogEvent("SaveSession");
15848  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveSession");
15849  AnsiString CurrentDateTimeStr = "", TimetableTimeStr = "", SessionFileStr = "";
15850  Screen->Cursor = TCursor(-11); // Hourglass;
15851  CurrentDateTimeStr = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
15852  // avoid characters in filename:= / \ : * ? " < > |
15853  TimetableTimeStr = Utilities->Format96HHMMSS(TrainController->TTClockTime);
15854  TimetableTimeStr = TimetableTimeStr.SubString(1, 2) + '.' + TimetableTimeStr.SubString(4, 2) + '.' + TimetableTimeStr.SubString(7, 2);
15855 // SessionFileStr = CurDir + "\\" + SESSION_DIR_NAME + "\\Session " + CurrentDateTimeStr + "; Timetable time " + TimetableTimeStr + "; " + RailwayTitle +
15856 // "; " + TimetableTitle + ".ssn";
15857  SessionFileStr = LoadSessionDialog->InitialDir + "\\Session " + CurrentDateTimeStr + "; Timetable time " + TimetableTimeStr + "; " + RailwayTitle +
15858  "; " + TimetableTitle + ".ssn";
15859  std::ofstream SessionFile(SessionFileStr.c_str());
15860  if(!(SessionFile.fail()))
15861  {
15862  Utilities->SaveFileString(SessionFile, ProgramVersion + ": ***Interface***" + FloatToStr(TrainController->ExcessLCDownMins));
15863 // added ExcessLC... at v2.2.0 as omitted earlier
15864  SaveInterface(0, SessionFile);
15865  // save track elements
15866  Utilities->SaveFileString(SessionFile, "***Track***");
15867  if(Track->UserGraphicVector.empty())
15868  {
15869  Track->SaveTrack(4, SessionFile, false); // false for no graphics (**Active elements** saved as marker)
15870  }
15871  else
15872  {
15873  Track->SaveTrack(11, SessionFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
15874  }
15875  // save text elements
15876  Utilities->SaveFileString(SessionFile, "***Text***");
15877  TextHandler->SaveText(2, SessionFile);
15878  // save PrefDir elements
15879  Utilities->SaveFileString(SessionFile, "***PrefDirs***");
15880  EveryPrefDir->SavePrefDirVector(2, SessionFile);
15881  if(!Track->UserGraphicVector.empty())
15882  {
15883  // save user graphics
15884  Track->SaveUserGraphics(2, SessionFile);
15885  }
15886  // save routes
15887  Utilities->SaveFileString(SessionFile, "***Routes***");
15888  AllRoutes->SaveRoutes(0, SessionFile);
15889  // save LockedRoutes
15890  Utilities->SaveFileString(SessionFile, "***Locked routes***");
15891  TrainController->SaveSessionLockedRoutes(0, SessionFile);
15892  // save ContinuationAutoSigEntries
15893  Utilities->SaveFileString(SessionFile, "***ContinuationAutoSigEntries***");
15895  // save BarriersDownVector
15896  Utilities->SaveFileString(SessionFile, "***BarriersDownVector***");
15897  Track->SaveSessionBarriersDownVector(0, SessionFile);
15898  // save timetable
15899  Utilities->SaveFileString(SessionFile, "***Timetable***");
15900  if(!(SaveTimetableToSessionFile(0, SessionFile, SessionFileStr)))
15901  {
15902  SessionFile.close();
15903  DeleteFile(SessionFileStr);
15904  Screen->Cursor = TCursor(-2); // Arrow;
15905  TrainController->StopTTClockMessage(3, "Error saving file, unable to save session");
15906  Utilities->CallLogPop(1150);
15907  return;
15908  }
15909  // save TimetableClock
15910  Utilities->SaveFileString(SessionFile, "***TimetableClock***");
15911  Utilities->SaveFileDouble(SessionFile, double(TrainController->TTClockTime));
15912 
15913  // save trains
15914  Utilities->SaveFileString(SessionFile, "***Trains***");
15915  TrainController->SaveSessionTrains(0, SessionFile);
15916  // save performance file
15917  Utilities->SaveFileString(SessionFile, "***Performance file***");
15918  SavePerformanceFile(0, SessionFile);
15919  Utilities->SaveFileString(SessionFile, "***End of performance file***");
15920 // addition at v2.4.0 to save TrainController->AvHoursIntValue + any future additions
15921  Utilities->SaveFileString(SessionFile, "***Additions after v2.3.1***");
15924  Utilities->SaveFileString(SessionFile, "***Failed Trains***");
15925  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
15926  {
15928  {
15931  }
15932  }
15933  Utilities->SaveFileInt(SessionFile, -1); // marker for end of failed trains
15934  Utilities->SaveFileString(SessionFile, "End of file at v2.4.0");
15935 // end of v2.4.0 addition
15936  SessionFile.close();
15937  TrainController->StopTTClockMessage(4, "Session saved: Session " + CurrentDateTimeStr + "; Timetable time " + TimetableTimeStr + "; " +
15938  RailwayTitle + "; " + TimetableTitle + ".ssn");
15939  LastNonCtrlOrShiftKeyDown = -1; //to restore the ability to reselect Ctrl S after a save (FormKeyUp doesn't work because the Interface form doesn't have focus)
15940  }
15941  else
15942  {
15943  TrainController->StopTTClockMessage(5, "Session file failed to open - reason not known, session unable to be saved.");
15944  }
15946  Screen->Cursor = TCursor(-2); // Arrow
15947  Utilities->CallLogPop(1141);
15948  }
15949  catch(const Exception &e)
15950  {
15951  ErrorLog(40, e.Message);
15952  }
15953 }
15954 
15955 // ---------------------------------------------------------------------------
15956 
15957 void TInterface::LoadSession(int Caller)
15958  // always loads in 'Paused' or 'PreStart' mode
15959 {
15960 // remember to load the timetable clock
15961 // no routes in build
15962 // prob need to set 'OperMode' then 'Paused', ensure have all info needed for these
15963 // set buttons enabled to correspond to flags on reloading. If no PrefDirs then disable all route buttons
15964 // set RlyFile true
15965  try
15966  {
15967  TrainController->LogEvent("LoadSession");
15968  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadSession");
15969  if(!ClearEverything(4))
15970  {
15971  Utilities->CallLogPop(1145);
15972  return;
15973  }
15974  LoadSessionDialog->Filter = "Session file (*.ssn)|*.ssn";
15975  if(LoadSessionDialog->Execute())
15976  {
15977  if(LoadSessionDialog->InitialDir != TPath::GetDirectoryName(LoadSessionDialog->FileName))//new at v2.6.0 to retain a new directory
15978  {
15979  LoadSessionDialog->InitialDir = TPath::GetDirectoryName(LoadSessionDialog->FileName);
15980  }
15981  TrainController->LogEvent("LoadSession " + LoadSessionDialog->FileName);
15982  Screen->Cursor = TCursor(-11); // Hourglass;
15983  if(SessionFileIntegrityCheck(0, AnsiString(LoadSessionDialog->FileName).c_str()))
15984  // if(true)
15985  {
15986  std::ifstream SessionFile(AnsiString(LoadSessionDialog->FileName).c_str());
15987  if(!(SessionFile.fail()))
15988  {
15989  TrainController->AvHoursIntValue = 0; // initial value set at v2.4.0 in case not changed later
15990  TrainController->MTBFHours = 0; // initial value set at v2.4.0 in case not changed later
15991  AnsiString TempString = Utilities->LoadFileString(SessionFile);
15992 // "version + : ***Interface***" + at v2.2.0 ExcessLCDownMins (omitted earlier)
15993 
15994  int LastCharBeforeFloat = TempString.LastDelimiter('*'); // added at v2.2.0
15995  if((LastCharBeforeFloat == 0) || (LastCharBeforeFloat == TempString.Length()))
15996  // can't find it or no value for Excess LCDownMins, either way count as zero
15997  {
15999  }
16000  else
16001  {
16002  AnsiString FloatStr = TempString.SubString(LastCharBeforeFloat + 1, TempString.Length() - LastCharBeforeFloat);
16003  if(!Utilities->CheckStringDouble(FloatStr)) // returns false for empty string or invalid double
16004  {
16006  }
16007  else
16008  {
16009  TrainController->ExcessLCDownMins = FloatStr.ToDouble();
16010  }
16011  } // end of v2.2.0 * v2.4.0 additions
16012 
16013  LoadInterface(0, SessionFile);
16014  int TempDisplayOffsetH = Display->DisplayOffsetH; // stored as they are zeroed when track loaded
16015  int TempDisplayOffsetV = Display->DisplayOffsetV;
16016  int TempDisplayOffsetHHome = Display->DisplayOffsetHHome;
16017  int TempDisplayOffsetVHome = Display->DisplayOffsetVHome;
16018  bool GraphicsFollow = false;
16019  // load track elements
16020  TempString = Utilities->LoadFileString(SessionFile); // ***Track***"
16021  Track->LoadTrack(4, SessionFile, GraphicsFollow);
16022  // load text elements
16023  TempString = Utilities->LoadFileString(SessionFile); // ***Text***"
16024  TextHandler->LoadText(1, SessionFile);
16025  // load PrefDir elements
16026  TempString = Utilities->LoadFileString(SessionFile); // "***PrefDirs***"
16027  EveryPrefDir->LoadPrefDir(1, SessionFile);
16028  if(GraphicsFollow)
16029  {
16030  Track->LoadGraphics(1, SessionFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME); // include path to Graphics folder);
16031  }
16033  {
16034  SessionFile.close();
16035  Screen->Cursor = TCursor(-2); // Arrow;
16036  ShowMessage("Corruption in preferred direction section of the session file, session can't be loaded");
16037  Utilities->CallLogPop(1438);
16038  return;
16039  }
16040  // load routes
16041  TempString = Utilities->LoadFileString(SessionFile); // "***Routes***"
16042  if(!AllRoutes->LoadRoutes(0, SessionFile))
16043  {
16044  SessionFile.close();
16045  Screen->Cursor = TCursor(-2); // Arrow;
16046  ShowMessage("Corruption in route section of the session file, session can't be loaded");
16047  Utilities->CallLogPop(1439);
16048  return;
16049  }
16050  // load LockedRoutes
16051  TempString = Utilities->LoadFileString(SessionFile); // "***Locked routes***"
16052  TrainController->LoadSessionLockedRoutes(0, SessionFile);
16053  // load ContinuationAutoSigEntries
16054  TempString = Utilities->LoadFileString(SessionFile); // "***ContinuationAutoSigEntries***"
16056  // load BarriersDownVector if present, but ensure backwards compatibility with earlier files
16057  TempString = Utilities->LoadFileString(SessionFile); // "***BarriersDownVector***" or "***Timetable***"
16058  if(TempString == "***BarriersDownVector***")
16059  {
16060  Track->LoadBarriersDownVector(0, SessionFile);
16061  TempString = Utilities->LoadFileString(SessionFile); // "***Timetable***"
16062  }
16063  // load timetable (marker "***Timetable***" already loaded)
16064  if(!(LoadTimetableFromSessionFile(0, SessionFile)))
16065  {
16066  SessionFile.close();
16067  Screen->Cursor = TCursor(-2); // Arrow;
16068  ShowMessage("Unable to load timetable section of the session file, session can't be loaded");
16069  Utilities->CallLogPop(1151);
16070  return;
16071  }
16072  // TimetableTitle should be loaded at this stage - check
16073  if(TimetableTitle == "")
16074  {
16075  SessionFile.close();
16076  Screen->Cursor = TCursor(-2); // Arrow;
16077  throw Exception("TimetableTitle null in LoadSession");
16078  }
16079  // load timetable clock
16080  TempString = Utilities->LoadFileString(SessionFile); // ***TimetableClock***
16081  TrainController->RestartTime = TDateTime(Utilities->LoadFileDouble(SessionFile)); // ClockTime set in RestartSessionOperMode;
16082  // load trains
16083  TempString = Utilities->LoadFileString(SessionFile); // ***Trains***
16084  TrainController->LoadSessionTrains(0, SessionFile);
16085  // load performance file + populate the performance log
16086  TempString = Utilities->LoadFileString(SessionFile); // ***Performance file***
16087  // first reset the performance file name and open it before reloading it
16088  PerformanceFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
16089  // avoid characters in filename:= / \ : * ? " < > |
16090  PerformanceFileName = CurDir + "\\" + PERFLOG_DIR_NAME + "\\Log " + PerformanceFileName + "; " + RailwayTitle + "; " +
16091  TimetableTitle + ".txt";
16092  Utilities->PerformanceFile.open(PerformanceFileName.c_str(), std::ios_base::out);
16093  if(Utilities->PerformanceFile.fail())
16094  {
16095  ShowMessage("Performance logfile failed to open, logs won't be saved. Ensure that there is a folder named " + PERFLOG_DIR_NAME +
16096  " in the folder where the 'Railway.exe' program file resides");
16097  }
16098  // now reload the performance file
16099  LoadPerformanceFile(0, SessionFile);
16100  // addition at v2.4.0
16101  char TempChar;
16102  SessionFile.get(TempChar);
16103  while(!SessionFile.eof() && ((TempChar == '\n') || (TempChar == '\0'))) // when emerge from here either have eof or '*'
16104  {
16105  SessionFile.get(TempChar);
16106  }
16107  if(SessionFile.eof()) // end of file
16108  {
16111  SessionFile.close(); // no TrainController->AvHoursIntValue & no failed trains
16112  }
16113  else
16114  {
16115  AnsiString DummyStr = Utilities->LoadFileString(SessionFile); // "**Additions after v2.3.1***" discarded (first '*' loaded earlier)
16116  TrainController->AvHoursIntValue = Utilities->LoadFileInt(SessionFile); // TrainController->AvHoursIntValue added at v2.4.0
16117  TrainController->NumFailures = Utilities->LoadFileInt(SessionFile); // number of train failures
16118  TrainController->MTBFHours = TrainController->AvHoursIntValue; // TTClockSpeed set to 1 in RestartSessionMode so no need to include here
16119  // now load any failed trains along with their OriginalPowerAtRail values
16120  DummyStr = Utilities->LoadFileString(SessionFile); // discard "***Failed Trains***"
16121  int ID = Utilities->LoadFileInt(SessionFile); // train ID or -1 for no more failed trains
16122  double PowerDouble;
16123  while(ID != -1)
16124  {
16125  PowerDouble = Utilities->LoadFileDouble(SessionFile); // ok TrainVector loaded at this stage (loaded in LoadSessionTrains)
16128  ID = Utilities->LoadFileInt(SessionFile);
16129  }
16130  SessionFile.close();
16131  }
16132  // deal with other settings
16133  Display->DisplayOffsetH = TempDisplayOffsetH; // reset to saved values
16134  Display->DisplayOffsetV = TempDisplayOffsetV;
16135  Display->DisplayOffsetHHome = TempDisplayOffsetHHome;
16136  Display->DisplayOffsetVHome = TempDisplayOffsetVHome;
16137  // now set attributes to 1 for all LCs with barriers down
16138  for(unsigned int x = 0; x < Track->BarriersDownVector.size(); x++)
16139  {
16141  }
16142  Track->ChangingLCVector.clear();
16143  Track->CalcHLocMinEtc(10);
16145  SetLevel1Mode(27);
16146  if(Level2OperMode == PreStart)
16147  // this section added at v1.3.2 as otherwise only in MainScreenMouseDown2, and if load a session without clicking mouse on screen
16148  { // then delay unspecified though seems to be 0
16149  PointsFlashDuration = 0.0;
16152  }
16153  else
16154  {
16158  }
16159  RlyFile = true;
16160  SetCaption(3);
16162  }
16163  }
16164  else
16165  {
16166  ShowMessage("Session file integrity check failed, unable to load session.");
16167  }
16168  Screen->Cursor = TCursor(-2); // Arrow;
16169  }
16170  Utilities->CallLogPop(1146);
16171  }
16172  catch(const Exception &e)
16173  {
16174  if((e.Message.Pos("esource") > 0) || (e.Message.Pos("arameter") > 0)) // 'Resource or Parameter, avoid capitals as may be OS dependent
16175  {
16176  Screen->Cursor = TCursor(-2); // Arrow;
16177  OutputLog1->Caption = "";
16178  OutputLog2->Caption = "";
16179  OutputLog3->Caption = "";
16180  OutputLog4->Caption = "";
16181  OutputLog5->Caption = "";
16182  OutputLog6->Caption = "";
16183  OutputLog7->Caption = "";
16184  OutputLog8->Caption = "";
16185  OutputLog9->Caption = "";
16186  OutputLog10->Caption = "";
16187  UnicodeString MessageStr =
16188  "Insufficient memory available to load the file, and partial load likely to be corrupt. Application will terminate. Try loading the session as the first action after reloading the program.";
16189 // UnicodeString MessageStr = "Last train loaded = " + UnicodeString(TrainController->LastTrainLoaded); //for debugging session train loading for many trains
16190  Application->MessageBox(MessageStr.c_str(), L"Out of memory", MB_OK | MB_ICONERROR);
16191  Application->Terminate();
16192  }
16193  else
16194  {
16195  ErrorLog(41, e.Message);
16196  }
16197  }
16198 }
16199 
16200 // ---------------------------------------------------------------------------
16201 
16202 void TInterface::SaveInterface(int Caller, std::ofstream &SessionFile)
16203 {
16204  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveInterface");
16205  if(Level2OperMode == PreStart)
16206  Utilities->SaveFileString(SessionFile, AnsiString("PreStart"));
16207  else
16208  Utilities->SaveFileString(SessionFile, AnsiString("NotPreStart")); // covers both Paused & Operating
16209  Utilities->SaveFileString(SessionFile, RailwayTitle);
16210  Utilities->SaveFileString(SessionFile, TimetableTitle);
16211  Utilities->SaveFileBool(SessionFile, PreferredRoute);
16212  Utilities->SaveFileBool(SessionFile, ConsecSignalsRoute);
16213  Utilities->SaveFileBool(SessionFile, AutoSigsFlag);
16214  Utilities->SaveFileInt(SessionFile, Display->DisplayOffsetH);
16215  Utilities->SaveFileInt(SessionFile, Display->DisplayOffsetV);
16220  Utilities->SaveFileString(SessionFile, OutputLog1->Caption);
16221  Utilities->SaveFileString(SessionFile, OutputLog2->Caption);
16222  Utilities->SaveFileString(SessionFile, OutputLog3->Caption);
16223  Utilities->SaveFileString(SessionFile, OutputLog4->Caption);
16224  Utilities->SaveFileString(SessionFile, OutputLog5->Caption);
16225  Utilities->SaveFileString(SessionFile, OutputLog6->Caption);
16226  Utilities->SaveFileString(SessionFile, OutputLog7->Caption);
16227  Utilities->SaveFileString(SessionFile, OutputLog8->Caption);
16228  Utilities->SaveFileString(SessionFile, OutputLog9->Caption);
16229  Utilities->SaveFileString(SessionFile, OutputLog10->Caption);
16230 
16252  // ExcessLCDownMins saved after ***Interface*** at v2.2.0 (omitted in error earlier)
16253  Utilities->CallLogPop(1211);
16254 }
16255 
16256 // ---------------------------------------------------------------------------
16257 void TInterface::LoadInterface(int Caller, std::ifstream &SessionFile)
16258 {
16259  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadInterface");
16260  AnsiString OpMode = Utilities->LoadFileString(SessionFile);
16261 
16262  if(OpMode == "PreStart")
16264  else
16266  RailwayTitle = Utilities->LoadFileString(SessionFile);
16267  SavedFileName = CurDir + "\\" + RAILWAY_DIR_NAME + "\\" + RailwayTitle + ".rly";
16268 
16269  TimetableTitle = Utilities->LoadFileString(SessionFile);
16270  PreferredRoute = Utilities->LoadFileBool(SessionFile);
16271  ConsecSignalsRoute = Utilities->LoadFileBool(SessionFile);
16272  AutoSigsFlag = Utilities->LoadFileBool(SessionFile);
16273  Display->DisplayOffsetH = Utilities->LoadFileInt(SessionFile);
16274  Display->DisplayOffsetV = Utilities->LoadFileInt(SessionFile);
16279  OutputLog1->Caption = Utilities->LoadFileString(SessionFile);
16280  OutputLog2->Caption = Utilities->LoadFileString(SessionFile);
16281  OutputLog3->Caption = Utilities->LoadFileString(SessionFile);
16282  OutputLog4->Caption = Utilities->LoadFileString(SessionFile);
16283  OutputLog5->Caption = Utilities->LoadFileString(SessionFile);
16284  OutputLog6->Caption = Utilities->LoadFileString(SessionFile);
16285  OutputLog7->Caption = Utilities->LoadFileString(SessionFile);
16286  OutputLog8->Caption = Utilities->LoadFileString(SessionFile);
16287  OutputLog9->Caption = Utilities->LoadFileString(SessionFile);
16288  OutputLog10->Caption = Utilities->LoadFileString(SessionFile);
16289 
16297  TrainController->LateDeps = Utilities->LoadFileInt(SessionFile);
16311  Utilities->CallLogPop(1212);
16312 }
16313 
16314 // ---------------------------------------------------------------------------
16315 
16316 bool TInterface::CheckInterface(int Caller, std::ifstream &SessionFile)
16317 {
16318  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CheckInterface");
16319 
16320  AnsiString OpMode = "";
16321 
16322  if(!Utilities->CheckAndReadFileString(SessionFile, OpMode))
16323  {
16324  Utilities->CallLogPop(1767);
16325  return false;
16326  }
16327  else if((OpMode != "PreStart") && (OpMode != "NotPreStart"))
16328  {
16329  Utilities->CallLogPop(1768);
16330  return false;
16331  }
16332  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile)) // RailwayTitle
16333  {
16334  Utilities->CallLogPop(1213);
16335  return false;
16336  }
16337  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile)) // TimetableTitle
16338  {
16339  Utilities->CallLogPop(1214);
16340  return false;
16341  }
16342  if(!Utilities->CheckFileBool(SessionFile))
16343  {
16344  Utilities->CallLogPop(1216);
16345  return false;
16346  }
16347  if(!Utilities->CheckFileBool(SessionFile))
16348  {
16349  Utilities->CallLogPop(1217);
16350  return false;
16351  }
16352  if(!Utilities->CheckFileBool(SessionFile))
16353  {
16354  Utilities->CallLogPop(1218);
16355  return false;
16356  }
16357  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16358  {
16359  Utilities->CallLogPop(1409);
16360  return false;
16361  }
16362  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16363  {
16364  Utilities->CallLogPop(1486);
16365  return false;
16366  }
16367  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16368  {
16369  Utilities->CallLogPop(1487);
16370  return false;
16371  }
16372  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16373  {
16374  Utilities->CallLogPop(1488);
16375  return false;
16376  }
16377  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16378  {
16379  Utilities->CallLogPop(1489);
16380  return false;
16381  }
16382  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16383  {
16384  Utilities->CallLogPop(1528);
16385  return false;
16386  }
16387  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16388  {
16389  Utilities->CallLogPop(1725);
16390  return false;
16391  }
16392  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16393  {
16394  Utilities->CallLogPop(1726);
16395  return false;
16396  }
16397  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16398  {
16399  Utilities->CallLogPop(1727);
16400  return false;
16401  }
16402  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16403  {
16404  Utilities->CallLogPop(1728);
16405  return false;
16406  }
16407  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16408  {
16409  Utilities->CallLogPop(1730);
16410  return false;
16411  }
16412  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16413  {
16414  Utilities->CallLogPop(1731);
16415  return false;
16416  }
16417  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16418  {
16419  Utilities->CallLogPop(1732);
16420  return false;
16421  }
16422  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16423  {
16424  Utilities->CallLogPop(1733);
16425  return false;
16426  }
16427  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16428  {
16429  Utilities->CallLogPop(1734);
16430  return false;
16431  }
16432  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16433  {
16434  Utilities->CallLogPop(1789);
16435  return false;
16436  }
16437 
16438  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16439  {
16440  Utilities->CallLogPop(1737);
16441  return false;
16442  }
16443  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16444  {
16445  Utilities->CallLogPop(1738);
16446  return false;
16447  }
16448  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16449  {
16450  Utilities->CallLogPop(1739);
16451  return false;
16452  }
16453  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16454  {
16455  Utilities->CallLogPop(1740);
16456  return false;
16457  }
16458  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16459  {
16460  Utilities->CallLogPop(1741);
16461  return false;
16462  }
16463  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16464  {
16465  Utilities->CallLogPop(1742);
16466  return false;
16467  }
16468  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16469  {
16470  Utilities->CallLogPop(1743);
16471  return false;
16472  }
16473  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16474  {
16475  Utilities->CallLogPop(1744);
16476  return false;
16477  }
16478  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16479  {
16480  Utilities->CallLogPop(1745);
16481  return false;
16482  }
16483  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16484  {
16485  Utilities->CallLogPop(1746);
16486  return false;
16487  }
16488  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16489  {
16490  Utilities->CallLogPop(1747);
16491  return false;
16492  }
16493  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16494  {
16495  Utilities->CallLogPop(1748);
16496  return false;
16497  }
16498  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16499  {
16500  Utilities->CallLogPop(1749);
16501  return false;
16502  }
16503  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16504  {
16505  Utilities->CallLogPop(1750);
16506  return false;
16507  }
16508  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16509  {
16510  Utilities->CallLogPop(1751);
16511  return false;
16512  }
16513  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16514  {
16515  Utilities->CallLogPop(1752);
16516  return false;
16517  }
16518 
16519  if(!Utilities->CheckFileDouble(SessionFile))
16520  {
16521  Utilities->CallLogPop(1753);
16522  return false;
16523  }
16524  if(!Utilities->CheckFileDouble(SessionFile))
16525  {
16526  Utilities->CallLogPop(1754);
16527  return false;
16528  }
16529  if(!Utilities->CheckFileDouble(SessionFile))
16530  {
16531  Utilities->CallLogPop(1755);
16532  return false;
16533  }
16534  if(!Utilities->CheckFileDouble(SessionFile))
16535  {
16536  Utilities->CallLogPop(1756);
16537  return false;
16538  }
16539  if(!Utilities->CheckFileDouble(SessionFile))
16540  {
16541  Utilities->CallLogPop(1757);
16542  return false;
16543  }
16544  Utilities->CallLogPop(1219);
16545  return true;
16546 }
16547 
16548 // ---------------------------------------------------------------------------
16549 
16550 bool TInterface::SaveTimetableToSessionFile(int Caller, std::ofstream &SessionFile, AnsiString SessionFileStr)
16551 {
16552  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveTimetableToSessionFile," + SessionFileStr);
16553  if(!FileExists(TempTTFileName))
16554  {
16555  Utilities->CallLogPop(1862);
16556  return false;
16557  }
16558 
16559  SessionFile.close(); // close & re-open in append & binary mode so LF characters copy as LFs & not CRLFs
16560  SessionFile.open(SessionFileStr.c_str(), std::ios_base::app | std::ios_base::binary); // file pointer set to end
16561 
16562  int Handle = FileOpen(TempTTFileName, fmOpenRead);
16563  int Count = 0;
16564 
16565  while(Handle < 0) // this type of file use failed when used in SaveTempTimetableFile when used to resave timetable.tmp from
16566  // temp .ttb file, but changed that to avoid so many rapid file actions in quick succession & been OK since
16567  // then, but nevertheless have 10 retries before giving message to be on safe side
16568  {
16569  Handle = FileOpen(TempTTFileName, fmOpenRead);
16570  Count++;
16571  Delay(1, 50); // 50mSec delay between tries
16572  if(Count > 10)
16573  {
16574  ShowMessage("Failed to open temporary timetable file. Unable to save the session");
16575  Utilities->CallLogPop(1221);
16576  return false;
16577  }
16578  }
16579 
16580  char *Buffer = new char[10000];
16581  int BytesRead;
16582 
16583  while(true)
16584  {
16585  BytesRead = FileRead(Handle, Buffer, 10000);
16586  SessionFile.write(Buffer, BytesRead);
16587  if(BytesRead < 10000)
16588  break;
16589  }
16590  delete Buffer;
16591  FileClose(Handle);
16592 
16593  SessionFile.close(); // close & re-open in append & text out mode as before so can write text
16594  SessionFile.open(SessionFileStr.c_str(), std::ios_base::app | std::ios_base::out); // file pointer set to end
16595 
16596  Utilities->SaveFileString(SessionFile, "***End***"); // marker for end of timetable
16597 // now need to save the TrainOperatingData so can be loaded back into the timetable as is
16598  Utilities->SaveFileInt(SessionFile, TrainController->TrainDataVector.size());
16599  for(unsigned int x = 0; x < TrainController->TrainDataVector.size(); x++)
16600  {
16601  Utilities->SaveFileInt(SessionFile, TrainController->TrainDataVector.at(x).TrainOperatingDataVector.size());
16602  for(unsigned int y = 0; y < TrainController->TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16603  {
16604  Utilities->SaveFileInt(SessionFile, TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).TrainID);
16605  Utilities->SaveFileInt(SessionFile, (short)(TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).EventReported));
16606  Utilities->SaveFileInt(SessionFile, (short)(TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).RunningEntry));
16607  }
16608  }
16609  Utilities->CallLogPop(1220);
16610  return true;
16611 }
16612 
16613 // ---------------------------------------------------------------------------
16614 
16615 bool TInterface::SaveTimetableToErrorFile(int Caller, std::ofstream &ErrorFile, AnsiString ErrorFileStr, AnsiString TimetableFileName)
16616 {
16617  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveTimetableToErrorFile," + ErrorFileStr + "," + TimetableFileName);
16618  if(!FileExists(TimetableFileName))
16619  {
16620  Utilities->CallLogPop(1863);
16621  return false;
16622  }
16623 
16624  ErrorFile.close(); // close & re-open in append & binary mode so LF characters copy as LFs & not CRLFs
16625  ErrorFile.open(ErrorFileStr.c_str(), std::ios_base::app | std::ios_base::binary); // file pointer set to end
16626 
16627  int Handle = FileOpen(TimetableFileName, fmOpenRead);
16628  int Count = 0;
16629 
16630  while(Handle < 0) // this type of file use failed when used in SaveTempTimetableFile when used to resave timetable.tmp from
16631  // temp .ttb file, but changed that to avoid so many rapid file actions in quick succession & been OK since
16632  // then, but nevertheless have 10 retries before giving message to be on safe side
16633  {
16634  Handle = FileOpen(TimetableFileName, fmOpenRead);
16635  Count++;
16636  Delay(5, 50); // 50mSec delay between tries
16637  if(Count > 10)
16638  {
16639  Utilities->CallLogPop(1835);
16640  return false;
16641  }
16642  }
16643 
16644  char *Buffer = new char[10000];
16645  int BytesRead;
16646 
16647  while(true)
16648  {
16649  BytesRead = FileRead(Handle, Buffer, 10000);
16650  ErrorFile.write(Buffer, BytesRead);
16651  if(BytesRead < 10000)
16652  break;
16653  }
16654  delete Buffer;
16655  FileClose(Handle);
16656 
16657  ErrorFile.close(); // close & re-open in append & text out mode as before so can write text
16658  ErrorFile.open(ErrorFileStr.c_str(), std::ios_base::app | std::ios_base::out); // file pointer set to end
16659 
16660  Utilities->SaveFileString(ErrorFile, "***End of timetable***"); // marker for end of timetable
16661  Utilities->CallLogPop(1836);
16662  return true;
16663 }
16664 
16665 // ---------------------------------------------------------------------------
16666 
16667 bool TInterface::LoadTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
16668  // the .ttb section is delimited by "***End***"
16669  // create the temporary timetable file in the working folder exactly like the original
16670 {
16671  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadTimetableFromSessionFile");
16672  // reset all message flags, stops them being given twice (shouldn't be needed here but add for safety) //new at v2.4.0
16673  TrainController->SSHigh = false;
16674  TrainController->MRSHigh = false;
16675  TrainController->MRSLow = false;
16676  TrainController->MassHigh = false;
16677  TrainController->BFHigh = false;
16678  TrainController->BFLow = false;
16679  TrainController->PwrHigh = false;
16680  TrainController->SigSHigh = false;
16681  TrainController->SigSLow = false;
16682  if((TempTTFileName != "") && FileExists(TempTTFileName))
16683  {
16684  DeleteFile(TempTTFileName);
16685  }
16686  int TempTTFileNumber = 0;
16687 
16688  while(FileExists(CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp"))
16689  {
16690  TempTTFileNumber++;
16691  }
16692  TempTTFileName = CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp";
16693 
16694  std::ofstream TTBFile(TempTTFileName.c_str()); // use text mode as SessionFile is in text mode, so CRLFs read as LFs, and LFs write as CRLFs.
16695  int Count;
16696  char Zero = '\0';
16697 
16698  if(!TTBFile.fail())
16699  {
16700  char *Buffer = new char[10000]; // can't use LoadFileString as that expects a '\0' delimiter
16701  char TempChar = (char)(SessionFile.peek()); // have a look at the next character, if it's '\n'
16702  if(TempChar == '\n')
16703  SessionFile.get(TempChar); // then get rid of it, else leave it in as part of the first line
16704  if(!SessionFile.getline(Buffer, 10000, '\0'))
16705  {
16706  TTBFile.close();
16707  DeleteFile(TempTTFileName);
16708  delete Buffer;
16709  Utilities->CallLogPop(1222);
16710  return false;
16711  }
16712  Count = 0;
16713  for(int x = 0; x < 10000; x++)
16714  {
16715  if(Buffer[x] != '\0')
16716  Count++;
16717  else
16718  break;
16719  }
16720  while(AnsiString(Buffer) != "***End***")
16721  {
16722  TTBFile.write(Buffer, Count);
16723  TTBFile.write(&Zero, 1);
16724 // TTBFile.write(&NewLine, 1);
16725  if(!SessionFile.getline(Buffer, 10000, '\0'))
16726  {
16727  TTBFile.close();
16728  DeleteFile(TempTTFileName);
16729  delete Buffer;
16730  Utilities->CallLogPop(1223);
16731  return false;
16732  }
16733  Count = 0;
16734  for(int x = 0; x < 10000; x++)
16735  {
16736  if(Buffer[x] != '\0')
16737  Count++;
16738  else
16739  break;
16740  }
16741  }
16742  TTBFile.close();
16743  delete Buffer;
16744 // SaveTempTimetableFile(1, TTBFileName); no need, already has required name
16745 // now create the internal timetable from the .tmp file
16746  bool GiveMessagesFalse = false;
16747  bool CheckLocationsExistInRailwayTrue = true;
16748  if(TrainController->TimetableIntegrityCheck(1, TempTTFileName.c_str(), GiveMessagesFalse, CheckLocationsExistInRailwayTrue))
16749  {
16750  std::ifstream TTBLFile(TempTTFileName.c_str(), std::ios_base::binary);
16751  if(TTBLFile.is_open())
16752  {
16753  bool SessionFileTrue = true;
16754  if(!(BuildTrainDataVectorForLoadFile(1, TTBLFile, GiveMessagesFalse, CheckLocationsExistInRailwayTrue, SessionFileTrue)))
16755  {
16756  TTBLFile.close();
16757  DeleteFile(TempTTFileName);
16758  Utilities->CallLogPop(1224);
16759  return false;
16760  }
16761  }
16762  else
16763  {
16764  DeleteFile(TempTTFileName);
16765  Utilities->CallLogPop(1225);
16766  return false;
16767  }
16768  } // if(FileIntegrityCheck(TTBFileName.c_str()))
16769  else
16770  {
16771  DeleteFile(TempTTFileName);
16772  Utilities->CallLogPop(1226);
16773  return false;
16774  }
16775 // DeleteFile(TempTTFileName); no, need to save it for later session saves
16776 
16777  // now need to load the TrainOperatingData so can be loaded back into the timetable
16778  int NumberOfTrainEntries = Utilities->LoadFileInt(SessionFile);
16779  if(NumberOfTrainEntries != (int)(TrainController->TrainDataVector.size()))
16780  {
16781  Utilities->CallLogPop(1811);
16782  return false;
16783  }
16784  for(int x = 0; x < NumberOfTrainEntries; x++)
16785  {
16786  int NumberOfTrains = Utilities->LoadFileInt(SessionFile);
16787  if(NumberOfTrains != (int)(TrainController->TrainDataVector.at(x).TrainOperatingDataVector.size()))
16788  {
16789  Utilities->CallLogPop(1812);
16790  return false;
16791  }
16792  for(int y = 0; y < NumberOfTrains; y++)
16793  {
16794  TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).TrainID = Utilities->LoadFileInt(SessionFile);
16795  TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).EventReported = (TActionEventType)(Utilities->LoadFileInt(SessionFile));
16796  TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).RunningEntry = (TRunningEntry)(Utilities->LoadFileInt(SessionFile));
16797  }
16798  }
16799  Utilities->CallLogPop(1227);
16800  return true;
16801  }
16802  else
16803  {
16804  Utilities->CallLogPop(1228);
16805  return false;
16806  }
16807 }
16808 
16809 // ---------------------------------------------------------------------------
16810 
16811 bool TInterface::CheckTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
16812  // the .ttb section is delimited by '\0' followed by "***End***" & has been saved in binary mode, i.e. no '\0'
16813  // string delimiters between entries, this check function just checks the (non-zero terminated) string entries in the file without
16814  // trying to build a timetable - that's done during load
16815 {
16816  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CheckTimetableFromSessionFile");
16817  AnsiString OutString;
16818 
16819  if(!Utilities->CheckAndReadFileString(SessionFile, OutString))
16820  {
16821  Utilities->CallLogPop(1229);
16822  return false;
16823  }
16824  while(OutString != "***End***")
16825  {
16826  if(!Utilities->CheckAndReadFileString(SessionFile, OutString))
16827  {
16828  Utilities->CallLogPop(1230);
16829  return false;
16830  }
16831  }
16832 // now need to check the TrainOperatingData, which was saved in text mode
16833  if(SessionFile.fail())
16834  {
16835  Utilities->CallLogPop(1231);
16836  return false;
16837  }
16838  int NumberOfTrainEntries;
16839 
16840  if(!Utilities->CheckAndReadFileInt(SessionFile, 0, 10000, NumberOfTrainEntries))
16841  {
16842  Utilities->CallLogPop(1232);
16843  return false;
16844  }
16845  for(int x = 0; x < NumberOfTrainEntries; x++)
16846  {
16847  int NumberOfTrains;
16848  if(!Utilities->CheckAndReadFileInt(SessionFile, 0, 10000, NumberOfTrains))
16849  {
16850  Utilities->CallLogPop(1233);
16851  return false;
16852  }
16853  for(int y = 0; y < NumberOfTrains; y++)
16854  {
16855  if(!Utilities->CheckFileInt(SessionFile, -1, 1000000)) // TrainID
16856  {
16857  Utilities->CallLogPop(1234);
16858  return false;
16859  }
16860  if(!Utilities->CheckFileInt(SessionFile, 0, 30)) // EventReported
16861  {
16862  Utilities->CallLogPop(1235);
16863  return false;
16864  }
16865  if(!Utilities->CheckFileInt(SessionFile, 0, 2)) // RunningEntry
16866  {
16867  Utilities->CallLogPop(1236);
16868  return false;
16869  }
16870  }
16871  }
16872  Utilities->CallLogPop(1237);
16873  return true;
16874 }
16875 
16876 // ---------------------------------------------------------------------------
16877 
16878 bool TInterface::BuildTrainDataVectorForLoadFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway, bool SessionFile)
16879 {
16880  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",BuildTrainDataVectorForLoadFile," + AnsiString((short)GiveMessages));
16881  TrainController->TrainDataVector.clear(); // get rid of any earlier timetable
16882  bool EndOfFile = false;
16883  int Count = 0;
16884  char *TrainTimetableString = new char[10000]; // enough for ~ 200 stations at 50 chars/station, should be adequate!
16885 
16886  while(!EndOfFile)
16887  {
16888  TTBLFile.getline(TrainTimetableString, 10000, '\0');
16889  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
16890  { // may still have eof even if read a line (no CRLF at end), and
16891  // if so need to process it
16892  EndOfFile = true;
16893  break;
16894  }
16895  AnsiString OneLine(TrainTimetableString);
16896  bool FinalCallTrue = true;
16897  while((Count == 0) && !TrainController->ProcessOneTimetableLine(3, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages,
16898  CheckLocationsExistInRailway)) // get rid of lines before the start time
16899  {
16900  TTBLFile.getline(TrainTimetableString, 10000, '\0');
16901  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
16902  {
16903  TTBLFile.close();
16904  throw Exception("Timetable FinalCall error - no start time on own line, Count = 0");
16905  }
16906  OneLine = AnsiString(TrainTimetableString);
16907  }
16908  // here when have accepted the start time
16909  if(Count == 0)
16910  {
16911  Count++; // increment past the start time
16912  TTBLFile.getline(TrainTimetableString, 10000, '\0'); // get next line after start time
16913  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
16914  {
16915  EndOfFile = true;
16916  OneLine = "";
16917  }
16918  else
16919  OneLine = AnsiString(TrainTimetableString);
16920  }
16921  if(!TrainController->ProcessOneTimetableLine(4, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages, CheckLocationsExistInRailway))
16922  {
16923  TTBLFile.close();
16924  throw Exception("Timetable FinalCall error in processing one timetable line, Count = " + AnsiString(Count));
16925  }
16926  if(EndOfFile && (Count < 2)) // Timetable must contain at least two relevant lines, one for start time and at least one train
16927  {
16928  TTBLFile.close();
16929  throw Exception("Timetable FinalCall error - too few or no relevant entries, Count = " + AnsiString(Count));
16930  }
16931  Count++;
16932  }
16933  TTBLFile.close();
16934  delete TrainTimetableString;
16935 // here when first pass actions completed successfully
16936  if(!TrainController->SecondPassActions(0, GiveMessages)) // Check for matching join/split HeadCodes, check increasing times & matching split/join
16937  // times, complete arrival & departure times for each TT line, check & complete train info for each type of start,
16938  // messages given in function if errors & vector cleared
16939  {
16940  if(GiveMessages)
16941  ShowMessage("Timetable secondary integrity check failed - unable to load");
16942  Utilities->CallLogPop(1238);
16943  return false;
16944  }
16945  else
16946  {
16947 // TimetableLoaded = true;
16948  if(!SessionFile) // new timetable being loaded so need new TimetableTitle, if SessionFile true then already have it from LoadInterface
16949  {
16950  for(int x = TimetableDialog->FileName.Length(); x > 0; x--)
16951  {
16952  if(TimetableDialog->FileName[x] == '\\')
16953  {
16954  TimetableTitle = TimetableDialog->FileName.SubString(x + 1, TimetableDialog->FileName.Length() - x - 4);
16955  SetCaption(4);
16956  break;
16957  }
16958  }
16959  }
16960 // if(GiveMessages) //only set BaseMode if have manually loaded a timetable changed for the below in v2.4.0
16961  if(!SessionFile) // only set BaseMode if have manually loaded a timetable, i.e SessionFile is false
16962  {
16963  Level1Mode = BaseMode;
16964  SetLevel1Mode(28);
16965  }
16966  }
16967  Utilities->CallLogPop(1239);
16968  return true;
16969 }
16970 
16971 // ---------------------------------------------------------------------------
16972 
16973 bool TInterface::BuildTrainDataVectorForValidateFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway)
16974 {
16975  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",BuildTrainDataVectorForValidateFile," + AnsiString((short)GiveMessages));
16976  TrainController->TrainDataVector.clear(); // get rid of any earlier timetable
16977  bool EndOfFile = false;
16978  int Count = 0;
16979  char *TrainTimetableString = new char[10000]; // enough for ~ 200 stations at 50 chars/station, should be adequate!
16980 
16981  while(!EndOfFile)
16982  {
16983  TTBLFile.getline(TrainTimetableString, 10000, '\0');
16984  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
16985  { // may still have eof even if read a line (no CRLF at end), and
16986  // if so need to process it
16987  EndOfFile = true;
16988  break;
16989  }
16990  AnsiString OneLine(TrainTimetableString);
16991  bool FinalCallTrue = true;
16992  while((Count == 0) && !TrainController->ProcessOneTimetableLine(0, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages,
16993  CheckLocationsExistInRailway)) // get rid of lines before the start time
16994  {
16995  TTBLFile.getline(TrainTimetableString, 10000, '\0');
16996  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
16997  {
16998  TTBLFile.close();
16999  throw Exception("Timetable FinalCall error - no start time on own line, Count = 0");
17000  }
17001  OneLine = AnsiString(TrainTimetableString);
17002  }
17003  // here when have accepted the start time
17004  if(Count == 0)
17005  {
17006  Count++; // increment past the start time
17007  TTBLFile.getline(TrainTimetableString, 10000, '\0'); // get next line after start time
17008  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
17009  {
17010  EndOfFile = true;
17011  OneLine = "";
17012  }
17013  else
17014  OneLine = AnsiString(TrainTimetableString);
17015  }
17016  if(!TrainController->ProcessOneTimetableLine(1, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages, CheckLocationsExistInRailway))
17017  {
17018  TTBLFile.close();
17019  throw Exception("Timetable FinalCall error in processing one timetable line, Count = " + AnsiString(Count));
17020  }
17021  if(EndOfFile && (Count < 2)) // Timetable must contain at least two relevant lines, one for start time and at least one train
17022  {
17023  TTBLFile.close();
17024  throw Exception("Timetable FinalCall error - too few or no relevant entries, Count = " + AnsiString(Count));
17025  }
17026  Count++;
17027  }
17028  TTBLFile.close();
17029  delete TrainTimetableString;
17030 // here when first pass actions completed successfully
17031  if(!TrainController->SecondPassActions(1, GiveMessages)) // Check for matching join/split HeadCodes, check increasing times & matching split/join
17032  // times, complete arrival & departure times for each TT line, check & complete train info for each type of start,
17033  // messages given in function if errors & vector cleared
17034  {
17035 // if(GiveMessages) ShowMessage("Timetable secondary integrity check failed");
17036 // above dropped in v2.4.0 as all called functions give own messages
17037  Utilities->CallLogPop(1665);
17038  return false;
17039  }
17040  Utilities->CallLogPop(1666);
17041  return true;
17042 }
17043 
17044 // ---------------------------------------------------------------------------
17045 
17046 bool TInterface::SessionFileIntegrityCheck(int Caller, AnsiString FileName)
17047 /* Here need to check as far as timetable, then go back and load the track, because the timetable compilation check
17048  relies on the track vector and map being in place. Won't affect the later load because the vector and map are cleared
17049  before loading.
17050 
17051  Although this appears cumbersome, I initially used tellg() & seekg() to reposition the file pointer without having to do
17052  all this backtracking. However after many problems I eventually found that tellg() sometimes returns false values,
17053  which cause problems when reloaded using seekg(). This must be a compiler problem, though I could find no mention of it
17054  in the CBuilder4 issues list or on the web. The full write-up is at the end of this unit.
17055 
17056  Also, with hindsight, I wish I had just saved and reloaded the timetable vectors rather than the text of the timetable. That
17057  would probably have been easier. To change it now though would cause compatibility problems with sessions created by earlier versions.
17058 */
17059 {
17060  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SessionFileIntegrityCheck," + FileName);
17061  std::ifstream InFile(FileName.c_str());
17062 // first pass as far as timetable
17063  int NumberOfActiveElements;
17064  bool GraphicsFollow = false;
17065 
17066  if(InFile.is_open())
17067  {
17069  // expected to be "***Interface***" for original version or "Version + : ***Interface***" for later releases + ExcessLCDownMins added as float after v2.2.0
17070  {
17071  InFile.close();
17072  Utilities->CallLogPop(1240);
17073  return false;
17074  }
17075  if(!CheckInterface(0, InFile))
17076  {
17077  InFile.close();
17078  Utilities->CallLogPop(1241);
17079  return false;
17080  }
17081  // check track elements
17082  if(!Utilities->CheckAndCompareFileString(InFile, "***Track***"))
17083  {
17084  InFile.close();
17085  Utilities->CallLogPop(1242);
17086  return false;
17087  }
17088  if(!Track->CheckTrackElementsInFile(2, NumberOfActiveElements, GraphicsFollow, InFile))
17089  {
17090  InFile.close();
17091  Utilities->CallLogPop(1243);
17092  return false;
17093  }
17094  if(InFile.fail())
17095  {
17096  InFile.close();
17097  Utilities->CallLogPop(1244);
17098  return false;
17099  }
17100  // check text elements
17101  if(!Utilities->CheckAndCompareFileString(InFile, "***Text***"))
17102  {
17103  InFile.close();
17104  Utilities->CallLogPop(1245);
17105  return false;
17106  }
17107  if(!TextHandler->CheckTextElementsInFile(1, InFile))
17108  {
17109  InFile.close();
17110  Utilities->CallLogPop(1246);
17111  return false;
17112  }
17113  if(InFile.fail())
17114  {
17115  InFile.close();
17116  Utilities->CallLogPop(1247);
17117  return false;
17118  }
17119  // check PrefDir elements
17120  if(!Utilities->CheckAndCompareFileString(InFile, "***PrefDirs***"))
17121  {
17122  InFile.close();
17123  Utilities->CallLogPop(1248);
17124  return false;
17125  }
17126  if(!EveryPrefDir->CheckOnePrefDir(1, NumberOfActiveElements, InFile))
17127  {
17128  InFile.close();
17129  Utilities->CallLogPop(1249);
17130  return false;
17131  }
17132  if(InFile.fail())
17133  {
17134  InFile.close();
17135  Utilities->CallLogPop(1250);
17136  return false;
17137  }
17138  // check graphics
17139  if(GraphicsFollow)
17140  {
17141  if(!Track->CheckUserGraphics(1, InFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME)) // include path to Graphics folder
17142  {
17143  InFile.close();
17144  Utilities->CallLogPop(2187);
17145  return false;
17146  }
17147  if(InFile.fail())
17148  {
17149  InFile.close();
17150  Utilities->CallLogPop(2188);
17151  return false;
17152  }
17153  }
17154  // check routes
17155  if(!Utilities->CheckAndCompareFileString(InFile, "***Routes***"))
17156  {
17157  InFile.close();
17158  Utilities->CallLogPop(1251);
17159  return false;
17160  }
17161  if(!AllRoutes->CheckRoutes(0, NumberOfActiveElements, InFile))
17162  {
17163  InFile.close();
17164  Utilities->CallLogPop(1252);
17165  return false;
17166  }
17167  if(InFile.fail())
17168  {
17169  InFile.close();
17170  Utilities->CallLogPop(1253);
17171  return false;
17172  }
17173  // check LockedRoutes
17174  if(!Utilities->CheckAndCompareFileString(InFile, "***Locked routes***"))
17175  {
17176  InFile.close();
17177  Utilities->CallLogPop(1254);
17178  return false;
17179  }
17180  if(!TrainController->CheckSessionLockedRoutes(0, InFile))
17181  {
17182  InFile.close();
17183  Utilities->CallLogPop(1255);
17184  return false;
17185  }
17186  if(InFile.fail())
17187  {
17188  InFile.close();
17189  Utilities->CallLogPop(1256);
17190  return false;
17191  }
17192  // check ContinuationAutoSigs
17193  if(!Utilities->CheckAndCompareFileString(InFile, "***ContinuationAutoSigEntries***"))
17194  {
17195  InFile.close();
17196  Utilities->CallLogPop(1257);
17197  return false;
17198  }
17200  {
17201  InFile.close();
17202  Utilities->CallLogPop(1258);
17203  return false;
17204  }
17205  if(InFile.fail())
17206  {
17207  InFile.close();
17208  Utilities->CallLogPop(1259);
17209  return false;
17210  }
17211  // check BarriersDownVector, but ensure backwards compatibility with earlier files which don't have this section
17212  AnsiString TempString = Utilities->LoadFileString(InFile);
17213  if((TempString != "***BarriersDownVector***") && (TempString != "***Timetable***"))
17214  {
17215  InFile.close();
17216  Utilities->CallLogPop(1964);
17217  return false;
17218  }
17219  if(TempString == "***BarriersDownVector***")
17220  {
17221  if(!Track->CheckActiveLCVector(0, InFile))
17222  {
17223  InFile.close();
17224  Utilities->CallLogPop(1965);
17225  return false;
17226  }
17227  if(InFile.fail())
17228  {
17229  InFile.close();
17230  Utilities->CallLogPop(1966);
17231  return false;
17232  }
17233  if(!Utilities->CheckAndCompareFileString(InFile, "***Timetable***"))
17234  {
17235  InFile.close();
17236  Utilities->CallLogPop(1260);
17237  return false;
17238  }
17239  }
17240  // check timetable (marker string already checked immediately above)
17241  if(!CheckTimetableFromSessionFile(0, InFile))
17242  {
17243  InFile.close();
17244  Utilities->CallLogPop(1261);
17245  return false;
17246  }
17247  if(InFile.fail())
17248  {
17249  InFile.close();
17250  Utilities->CallLogPop(1262);
17251  return false;
17252  }
17253  }
17254  else
17255  {
17256  InFile.close();
17257  ShowMessage("Session file failed to open - reason not known, unable to load session.");
17258  Utilities->CallLogPop(1263);
17259  return false;
17260  }
17261 
17262 // now ready for the 2nd pass for timetable loading and checking
17263  InFile.close();
17264  InFile.open(FileName.c_str());
17265  if(InFile.is_open())
17266  {
17268  {
17269  InFile.close();
17270  Utilities->CallLogPop(1264);
17271  return false;
17272  }
17273  if(!CheckInterface(1, InFile))
17274  {
17275  InFile.close();
17276  Utilities->CallLogPop(1265);
17277  return false;
17278  }
17279  // load track elements
17280  if(!Utilities->CheckAndCompareFileString(InFile, "***Track***"))
17281  {
17282  InFile.close();
17283  Utilities->CallLogPop(1266);
17284  return false;
17285  }
17286  bool GraphicsFollow = false;
17287  Track->LoadTrack(2, InFile, GraphicsFollow); // load the track this time
17288  if(InFile.fail())
17289  {
17290  InFile.close();
17291  Utilities->CallLogPop(1267);
17292  return false;
17293  }
17294  // check text elements
17295  if(!Utilities->CheckAndCompareFileString(InFile, "***Text***"))
17296  {
17297  InFile.close();
17298  Utilities->CallLogPop(1268);
17299  return false;
17300  }
17301  if(!TextHandler->CheckTextElementsInFile(2, InFile))
17302  {
17303  InFile.close();
17304  Utilities->CallLogPop(1269);
17305  return false;
17306  }
17307  if(InFile.fail())
17308  {
17309  InFile.close();
17310  Utilities->CallLogPop(1270);
17311  return false;
17312  }
17313  // check PrefDir elements
17314  if(!Utilities->CheckAndCompareFileString(InFile, "***PrefDirs***"))
17315  {
17316  InFile.close();
17317  Utilities->CallLogPop(1271);
17318  return false;
17319  }
17320  if(!EveryPrefDir->CheckOnePrefDir(2, NumberOfActiveElements, InFile))
17321  {
17322  InFile.close();
17323  Utilities->CallLogPop(1272);
17324  return false;
17325  }
17326  if(InFile.fail())
17327  {
17328  InFile.close();
17329  Utilities->CallLogPop(1273);
17330  return false;
17331  }
17332  // check graphics
17333  if(GraphicsFollow)
17334  {
17335  if(!Track->CheckUserGraphics(2, InFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME)) // include path to Graphics folder
17336  {
17337  InFile.close();
17338  Utilities->CallLogPop(2189);
17339  return false;
17340  }
17341  if(InFile.fail())
17342  {
17343  InFile.close();
17344  Utilities->CallLogPop(2190);
17345  return false;
17346  }
17347  }
17348  // check routes
17349  if(!Utilities->CheckAndCompareFileString(InFile, "***Routes***"))
17350  {
17351  InFile.close();
17352  Utilities->CallLogPop(1274);
17353  return false;
17354  }
17355  if(!AllRoutes->CheckRoutes(1, NumberOfActiveElements, InFile))
17356  {
17357  InFile.close();
17358  Utilities->CallLogPop(1275);
17359  return false;
17360  }
17361  if(InFile.fail())
17362  {
17363  InFile.close();
17364  Utilities->CallLogPop(1276);
17365  return false;
17366  }
17367  // check LockedRoutes
17368  if(!Utilities->CheckAndCompareFileString(InFile, "***Locked routes***"))
17369  {
17370  InFile.close();
17371  Utilities->CallLogPop(1277);
17372  return false;
17373  }
17374  if(!TrainController->CheckSessionLockedRoutes(1, InFile))
17375  {
17376  InFile.close();
17377  Utilities->CallLogPop(1278);
17378  return false;
17379  }
17380  if(InFile.fail())
17381  {
17382  InFile.close();
17383  Utilities->CallLogPop(1279);
17384  return false;
17385  }
17386  // check ContinuationAutoSigs
17387  if(!Utilities->CheckAndCompareFileString(InFile, "***ContinuationAutoSigEntries***"))
17388  {
17389  InFile.close();
17390  Utilities->CallLogPop(1280);
17391  return false;
17392  }
17394  {
17395  InFile.close();
17396  Utilities->CallLogPop(1281);
17397  return false;
17398  }
17399  if(InFile.fail())
17400  {
17401  InFile.close();
17402  Utilities->CallLogPop(1282);
17403  return false;
17404  }
17405  // check BarriersDownVector, but ensure backwards compatibility with earlier files which don't have this section
17406  AnsiString TempString = Utilities->LoadFileString(InFile);
17407  if((TempString != "***BarriersDownVector***") && (TempString != "***Timetable***"))
17408  {
17409  InFile.close();
17410  Utilities->CallLogPop(1967);
17411  return false;
17412  }
17413  if(TempString == "***BarriersDownVector***")
17414  {
17415  if(!Track->CheckActiveLCVector(0, InFile))
17416  {
17417  InFile.close();
17418  Utilities->CallLogPop(1968);
17419  return false;
17420  }
17421  if(InFile.fail())
17422  {
17423  InFile.close();
17424  Utilities->CallLogPop(1969);
17425  return false;
17426  }
17427  if(!Utilities->CheckAndCompareFileString(InFile, "***Timetable***"))
17428  {
17429  InFile.close();
17430  Utilities->CallLogPop(1283);
17431  return false;
17432  }
17433  }
17434  // check timetable (marker string already checked)
17435  if(!LoadTimetableFromSessionFile(1, InFile))
17436  {
17437  InFile.close();
17438  Utilities->CallLogPop(1284);
17439  return false;
17440  }
17441  if(InFile.fail())
17442  {
17443  InFile.close();
17444  Utilities->CallLogPop(1285);
17445  return false;
17446  }
17447  // check timetable clock
17448  if(!Utilities->CheckAndCompareFileString(InFile, "***TimetableClock***"))
17449  {
17450  InFile.close();
17451  Utilities->CallLogPop(1286);
17452  return false;
17453  }
17454  if(!Utilities->CheckFileDouble(InFile))
17455  {
17456  InFile.close();
17457  Utilities->CallLogPop(1287);
17458  return false;
17459  }
17460  // check trains
17461  if(!Utilities->CheckAndCompareFileString(InFile, "***Trains***"))
17462  {
17463  InFile.close();
17464  Utilities->CallLogPop(1288);
17465  return false;
17466  }
17467  if(!TrainController->CheckSessionTrains(0, InFile))
17468  {
17469  InFile.close();
17470  Utilities->CallLogPop(1289);
17471  return false;
17472  }
17473  if(InFile.fail())
17474  {
17475  InFile.close();
17476  Utilities->CallLogPop(1290);
17477  return false;
17478  }
17479  if(!Utilities->CheckAndCompareFileString(InFile, "***Performance file***"))
17480  {
17481  InFile.close();
17482  Utilities->CallLogPop(1291);
17483  return false;
17484  }
17485  if(!CheckPerformanceFile(0, InFile))
17486  {
17487  InFile.close();
17488  Utilities->CallLogPop(1292);
17489  return false;
17490  }
17491  char TempChar;
17492  InFile.get(TempChar);
17493  while(!InFile.eof() && ((TempChar == '\n') || (TempChar == '\0'))) // when emerge from here either have eof or '*'
17494  {
17495  InFile.get(TempChar);
17496  }
17497  if(!InFile.eof()) // additional checks needed
17498  {
17499  if(!Utilities->CheckFileString(InFile))
17500  {
17501  InFile.close();
17502  Utilities->CallLogPop(2198);
17503  return false;
17504  }
17505  if(!Utilities->CheckFileInt(InFile, 0, 1000000)) // TrainController->AvHoursIntValue
17506  {
17507  InFile.close();
17508  Utilities->CallLogPop(2199);
17509  return false;
17510  }
17511  if(!Utilities->CheckFileInt(InFile, 0, 1000000)) // number of train failures
17512  {
17513  InFile.close();
17514  Utilities->CallLogPop(2200);
17515  return false;
17516  }
17517  // now check any failed trains along with their OriginalPowerAtRail values
17518  Utilities->CheckFileString(InFile); // discard "***Failed Trains***"
17519  int IDVal;
17520  if(!Utilities->CheckAndReadFileInt(InFile, -1, 1000000, IDVal)) // train ID or -1 for no more failed trains,
17521  {
17522  InFile.close();
17523  Utilities->CallLogPop(2201);
17524  return false;
17525  }
17526  double PowerDouble;
17527  while(IDVal != -1)
17528  {
17529  Utilities->CheckFileDouble(InFile); // original power
17530  if(!Utilities->CheckAndReadFileInt(InFile, -1, 1000000, IDVal))
17531  {
17532  InFile.close();
17533  Utilities->CallLogPop(2202);
17534  return false;
17535  }
17536  }
17537  }
17538  InFile.close();
17539  }
17540  else
17541  {
17542  InFile.close();
17543  Utilities->CallLogPop(1293);
17544  return false;
17545  }
17546  Utilities->CallLogPop(1294);
17547  return true;
17548 }
17549 
17550 // ---------------------------------------------------------------------------
17551 
17552 void TInterface::LoadPerformanceFile(int Caller, std::ifstream &InFile)
17553  // Note that the file integrity has already been checked using CheckPerformanceFile
17554 {
17555  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadPerformanceFile");
17556  AnsiString TempString = "", Line1 = "", Line2 = "", Line3 = "", Line4 = "", Line5 = "";
17557  char *Buffer = new char[1000];
17558  char TempChar;
17559 
17560  InFile.get(TempChar); // '\n'
17561  InFile.getline(Buffer, 1000);
17562  TempString = AnsiString(Buffer);
17563  while(TempString != "***End of performance file***")
17564  {
17565  PerformanceLogBox->Lines->Add(TempString);
17566  Utilities->PerformanceFile << TempString.c_str() << '\n';
17567  InFile.getline(Buffer, 1000);
17568  TempString = AnsiString(Buffer);
17569  }
17570  delete Buffer;
17571  Utilities->CallLogPop(1295);
17572 }
17573 
17574 // ---------------------------------------------------------------------------
17575 
17576 bool TInterface::CheckPerformanceFile(int Caller, std::ifstream &InFile)
17577 {
17578  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CheckPerformanceFile");
17579  AnsiString TempString = "";
17580  char TempChar;
17581 
17582  InFile.get(TempChar);
17583  if(TempChar != '\n')
17584  {
17585  Utilities->CallLogPop(1296);
17586  return false;
17587  }
17588  if(!Utilities->CheckAndReadFileString(InFile, TempString))
17589  {
17590  Utilities->CallLogPop(1297);
17591  return false;
17592  }
17593  while(TempString != "***End of performance file***")
17594  {
17595  if(!Utilities->CheckAndReadFileString(InFile, TempString))
17596  {
17597  Utilities->CallLogPop(1298);
17598  return false;
17599  }
17600  }
17601  Utilities->CallLogPop(1299);
17602  return true;
17603 }
17604 
17605 // ---------------------------------------------------------------------------
17606 
17607 void TInterface::SavePerformanceFile(int Caller, std::ofstream &OutFile)
17608 {
17609  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SavePerformanceFile");
17610  AnsiString Text = PerformanceLogBox->Text;
17611 
17612  while(Text != "")
17613  {
17614  AnsiString OneLine = Text.SubString(1, Text.Pos('\x0D'));
17615  while((OneLine.Length() > 0) && OneLine[OneLine.Length()] < ' ')
17616  OneLine.SetLength(OneLine.Length() - 1); // get rid of trailing control characters
17617  Text = Text.SubString(Text.Pos('\x0D'), Text.Length());
17618  while((Text.Length() > 0) && Text[1] < ' ')
17619  Text = Text.SubString(2, (Text.Length() - 1)); // get rid of leading control characters
17620  OutFile << OneLine.c_str() << '\n';
17621  }
17622  Utilities->CallLogPop(1300);
17623 }
17624 
17625 // ---------------------------------------------------------------------------
17626 
17628 {
17629  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetRouteButtonsInfoCaptionAndRouteNotStarted");
17630  if(EveryPrefDir->PrefDirSize() > 0)
17631  {
17632  if(AutoSigsFlag)
17633  {
17634  AutoSigsButton->Enabled = false;
17635  SigPrefButton->Enabled = true;
17636  UnrestrictedButton->Enabled = true;
17637  InfoPanel->Visible = true;
17638  if(Level2OperMode == PreStart)
17639  InfoPanel->Caption = "PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
17640  else
17641  InfoPanel->Caption = "OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
17642  InfoCaptionStore = InfoPanel->Caption;
17643  }
17644  else if(ConsecSignalsRoute) // PreferredRoute always same as ConsecSignalsRoute
17645  {
17646  AutoSigsButton->Enabled = true;
17647  SigPrefButton->Enabled = false;
17648  UnrestrictedButton->Enabled = true;
17649  InfoPanel->Visible = true;
17650  if(Level2OperMode == PreStart)
17651  InfoPanel->Caption = "PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
17652  else
17653  InfoPanel->Caption = "OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
17654  InfoCaptionStore = InfoPanel->Caption;
17655  }
17656  else
17657  {
17658  AutoSigsButton->Enabled = true;
17659  SigPrefButton->Enabled = true;
17660  UnrestrictedButton->Enabled = false;
17661  InfoPanel->Visible = true;
17662  if(Level2OperMode == PreStart)
17663  InfoPanel->Caption = "PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17664  else
17665  InfoPanel->Caption = "OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17666  InfoCaptionStore = InfoPanel->Caption;
17667  }
17668  }
17669  else
17670  {
17671  AutoSigsButton->Enabled = false;
17672  SigPrefButton->Enabled = false;
17673  UnrestrictedButton->Enabled = false;
17674  InfoPanel->Visible = true;
17675  if(Level2OperMode == PreStart)
17676  InfoPanel->Caption = "PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17677  else
17678  InfoPanel->Caption = "OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17679  InfoCaptionStore = InfoPanel->Caption;
17680  }
17682  {
17683  RouteCancelButton->Enabled = true;
17684  }
17685  else
17686  {
17687  RouteCancelButton->Enabled = false;
17688  }
17690  AutoRouteStartMarker->PlotOriginal(37, Display); // so start marker will replot if had selected start before pause & zoom
17693  Utilities->CallLogPop(1301);
17694 }
17695 
17696 // ---------------------------------------------------------------------------
17697 
17699 {
17700  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetPausedOrZoomedInfoCaption");
17701  if(Display->ZoomOutFlag)
17702  {
17703  InfoPanel->Visible = true;
17704  InfoPanel->Caption = "Left click screen to zoom in at that position";
17705  }
17706  else if(Level2OperMode == Paused)
17707  {
17708  InfoPanel->Visible = true;
17709  InfoPanel->Caption = "PAUSED: Railway state changes disabled";
17710  }
17711 // otherwise do nothing
17712  Utilities->CallLogPop(1302);
17713 }
17714 
17715 // ---------------------------------------------------------------------------
17716 
17718 {
17719  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",DisableRouteButtons");
17720  RouteCancelButton->Enabled = false;
17721  AutoSigsButton->Enabled = false;
17722  SigPrefButton->Enabled = false;
17723  UnrestrictedButton->Enabled = false;
17724  Utilities->CallLogPop(1303);
17725 }
17726 
17727 // ---------------------------------------------------------------------------
17728 
17730  // no need for call logging as already failed
17731 {
17732 /*
17733  In order to reload as a session file:
17734 
17735  NB: Don't change it to a .txt file, as the '\0' characters [shown as a small square in wordpad] will be changed to spaces if it is subsequently saved
17736  strip out:-
17737 
17738  [since adding user graphics after prefdirs need to take this into account]
17739 
17740  up to but excluding ***Interface***
17741  from & including ***ConstructPrefDir PrefDirVector***
17742  to but excluding ***PrefDirs***
17743  if there is a single line ***UserGraphics*** delete it (won't be present if no graphics)
17744  from & including ***ConstructRoute PrefDirVector***
17745  to but excluding ***Routes***
17746  from & including ***ChangingLCVector*** to but excluding ***Timetable*** [if have ***No timetable loaded*** then can't use as a session file]
17747  from & including ***No editing timetable*** or ***Editing timetable - [title]***
17748  to but excluding ***TimetableClock***
17749  and save as a .ssn file.
17750 
17751  In order to load as a railway file:
17752 
17753  NB: Don't change it to a .txt file, as the '\0' characters will be changed to spaces if it is subsequently saved
17754 
17755  note or copy the version information at the top of the file
17756  copy the two numbers on rows 7 & 8 below ***Interface*** (i.e ***Interface*** = row 0) on their own lines immediately after the ***Track*** line (these become DisplayOffsetH & V)
17757  strip out up to but excluding ***Track*** - this is needed to keep the \0 entry at end of ***Track*** [shown as a small square in wordpad]
17758  add the version number either before or instead of ***Track***, ensuring that the \0 is retained
17759  the next line after the two insertions should contain the number of active elements.
17760  strip out ***Text*** including the \0
17761  strip out from & including ***ConstructPrefDir PrefDirVector*** to & including ***PrefDirs*** (and the \0's)
17762  strip out ***UserGraphics*** including the \0
17763  strip out from & including ***ConstructRoute PrefDirVector*** to the end of the file
17764  rename as .dev or .rly file
17765 
17766  BUT - note that signals (and points, though they won't show) will be set as they were left. To reset to red, load a suitable timetable & select
17767  'Operate' then 'Exit operation'.
17768 */
17769 
17770 /*
17771  In order to extract a timetable:
17772 
17773  NB: Don't change it to a .txt file, as the '\0' characters will be changed to spaces if it is subsequently saved
17774 
17775  set wordwrap to window on
17776  strip out all to and including ***Timetable*** or ***Editing timetable.... depending which is to be saved
17777  ensure any text before start time ends with /0, otherwise don't need the \0
17778  strip out all after the final /0 immediately before ***End*** or ***End of timetable***, but ensure leave the final /0
17779  save as a .ttb file
17780 */
17781 
17782  Screen->Cursor = TCursor(-11); // Hourglass;
17783  AnsiString ErrorFileStr = CurDir + "\\errorlog.err";
17784  std::ofstream ErrorFile(ErrorFileStr.c_str());
17785 
17786  if(!(ErrorFile.fail()))
17787  {
17788 // save mouse position relative to mainscreen
17789  int ScreenX = Mouse->CursorPos.x - MainScreen->ClientOrigin.x;
17790  int ScreenY = Mouse->CursorPos.y - MainScreen->ClientOrigin.y;
17791  AnsiString MouseStr = "Posx: " + AnsiString(ScreenX) + "; Posy: " + AnsiString(ScreenY);
17792  Utilities->SaveFileString(ErrorFile, MouseStr);
17793  Utilities->SaveFileInt(ErrorFile, MissedTicks);
17794  Utilities->SaveFileInt(ErrorFile, TotalTicks);
17795 
17796 // save call stack
17797  Utilities->SaveFileString(ErrorFile, "***Call stack***");
17798  for(unsigned int x = 0; x < Utilities->CallLog.size(); x++)
17799  {
17800  AnsiString Item = Utilities->CallLog.at(x);
17801  ErrorFile << Item.c_str() << '\n';
17802  }
17803 // save event log
17804  Utilities->SaveFileString(ErrorFile, "***Event log***");
17805  for(unsigned int x = 0; x < Utilities->EventLog.size(); x++)
17806  {
17807  AnsiString Item = Utilities->EventLog.at(x);
17808  ErrorFile << Item.c_str() << '\n';
17809  }
17810 // save interface
17811  Utilities->SaveFileString(ErrorFile, "***Interface***");
17812  SaveInterface(1, ErrorFile);
17813 // save track elements
17814  Utilities->SaveFileString(ErrorFile, "***Track***");
17815  if(Track->UserGraphicVector.empty())
17816  {
17817  Track->SaveTrack(2, ErrorFile, false); // false for no graphics (**Active elements** saved as marker)
17818  }
17819  else
17820  {
17821  Track->SaveTrack(12, ErrorFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
17822  }
17823 // save text elements
17824  Utilities->SaveFileString(ErrorFile, "***Text***");
17825  TextHandler->SaveText(3, ErrorFile);
17826 // save ConstructPrefDir PrefDirVector elements
17827  Utilities->SaveFileString(ErrorFile, "***ConstructPrefDir PrefDirVector***");
17828  ConstructPrefDir->SavePrefDirVector(7, ErrorFile);
17829 // save ConstructPrefDir SearchVector elements
17830  Utilities->SaveFileString(ErrorFile, "***ConstructPrefDir SearchVector***");
17831  ConstructPrefDir->SaveSearchVector(0, ErrorFile);
17832 // save EveryPrefDir elements
17833  Utilities->SaveFileString(ErrorFile, "***PrefDirs***");
17834  EveryPrefDir->SavePrefDirVector(3, ErrorFile);
17835  if(!Track->UserGraphicVector.empty())
17836  {
17837  // save user graphics
17838  Utilities->SaveFileString(ErrorFile, "***UserGraphics***");
17839  Track->SaveUserGraphics(3, ErrorFile);
17840  }
17841 // save ConstructRoute PrefDirVector
17842  Utilities->SaveFileString(ErrorFile, "***ConstructRoute PrefDirVector***");
17843  ConstructRoute->SavePrefDirVector(4, ErrorFile);
17844 // save ConstructRoute SearchVector
17845  Utilities->SaveFileString(ErrorFile, "***ConstructRoute SearchVector***");
17846  ConstructRoute->SaveSearchVector(1, ErrorFile);
17847 // save AllRoutes
17848  Utilities->SaveFileString(ErrorFile, "***Routes***");
17849  AllRoutes->SaveRoutes(1, ErrorFile);
17850 // save LockedRoutes
17851  Utilities->SaveFileString(ErrorFile, "***Locked routes***");
17853 // save ContinuationAutoSigEntries
17854  Utilities->SaveFileString(ErrorFile, "***ContinuationAutoSigEntries***");
17856 // save BarriersDownVector
17857  Utilities->SaveFileString(ErrorFile, "***BarriersDownVector***");
17858  Track->SaveSessionBarriersDownVector(1, ErrorFile);
17859 // save ChangingLCVector
17860  Utilities->SaveFileString(ErrorFile, "***ChangingLCVector***");
17861  Track->SaveChangingLCVector(0, ErrorFile);
17862 // save loaded timetable
17863  if(TimetableTitle == "")
17864  Utilities->SaveFileString(ErrorFile, "***No timetable loaded***");
17865  else
17866  {
17867  Utilities->SaveFileString(ErrorFile, "***Timetable***");
17868  if(!(SaveTimetableToSessionFile(1, ErrorFile, ErrorFileStr)))
17869  {
17870  Utilities->SaveFileString(ErrorFile, "***Loaded timetable failed to save***");
17871  }
17872  }
17873 // save editing timetable
17874  if(CreateEditTTTitle == "")
17875  Utilities->SaveFileString(ErrorFile, "***No editing timetable***");
17876  else
17877  {
17878  Utilities->SaveFileString(ErrorFile, "***Editing timetable - " + CreateEditTTTitle + "***");
17879  if(!(SaveTimetableToErrorFile(1, ErrorFile, ErrorFileStr, CreateEditTTFileName)))
17880  {
17881  Utilities->SaveFileString(ErrorFile, "***Editing timetable failed to save***");
17882  }
17883  }
17884 // save TimetableClock
17885  Utilities->SaveFileString(ErrorFile, "***TimetableClock***");
17886  Utilities->SaveFileDouble(ErrorFile, double(TrainController->TTClockTime));
17887 // save trains
17888  Utilities->SaveFileString(ErrorFile, "***Trains***");
17889  TrainController->SaveSessionTrains(1, ErrorFile);
17890 // save performance file
17891  Utilities->SaveFileString(ErrorFile, "***Performance file***");
17892  SavePerformanceFile(1, ErrorFile);
17893  Utilities->SaveFileString(ErrorFile, "***End of performance file***");
17894 // addition at v2.4.1 to save TrainController->AvHoursIntValue + any future additions
17895  Utilities->SaveFileString(ErrorFile, "***Additions after v2.3.1***");
17898  Utilities->SaveFileString(ErrorFile, "***Failed Trains***");
17899  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
17900  {
17902  {
17905  }
17906  }
17907  Utilities->SaveFileInt(ErrorFile, -1); // marker for end of failed trains
17908  Utilities->SaveFileString(ErrorFile, "End of file at v2.4.1");
17909 // end of v2.4.1 addition
17910 
17911  ErrorFile.close();
17912  }
17913  else
17914  {
17915  TrainController->StopTTClockMessage(6, "Error file failed to open, error log won't be saved.");
17916  }
17917  Screen->Cursor = TCursor(-2); // Arrow
17918 }
17919 
17920 // ---------------------------------------------------------------------------
17921 
17922 void TInterface::SaveTempTimetableFile(int Caller, AnsiString InFileName)
17923  // the .ttb section is delimited by '\n' followed by "***End***"
17924  // first create a .ttb file in the working folder exactly like the original
17925 
17926  // Note: this type of file use failed when used to resave timetable.tmp from temp .ttb file, but changed that to avoid so many rapid
17927  // file actions in quick succession & been OK since then, but nevertheless keep the 10 retries before giving message to be on safe side
17928 {
17929  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveTempTimetableFile");
17930  if((TempTTFileName != "") && FileExists(TempTTFileName))
17931  {
17932  DeleteFile(TempTTFileName);
17933  }
17934  int TempTTFileNumber = 0;
17935 
17936  while(FileExists(CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp"))
17937  {
17938  TempTTFileNumber++;
17939  }
17940  TempTTFileName = CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp";
17941  int InHandle = FileOpen(InFileName, fmOpenRead);
17942  int Count = 0;
17943 
17944  while(InHandle < 0) // sometimes fails, have 10 retries before giving message
17945  {
17946  InHandle = FileOpen(InFileName, fmOpenRead);
17947  Count++;
17948  Delay(2, 50); // 50mSec delay between tries
17949  if(Count > 10)
17950  {
17951  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
17952  Utilities->CallLogPop(1400);
17953  return;
17954  }
17955  }
17956  int OutHandle = FileCreate(TempTTFileName);
17957 
17958  Count = 0;
17959  while(OutHandle < 0) // sometimes fails, have 10 retries before giving message
17960  {
17961  OutHandle = FileCreate(TempTTFileName);
17962  Count++;
17963  Delay(3, 50); // 50mSec delay between tries
17964  if(Count > 10)
17965  {
17966  ShowMessage("Failed to save temporary timetable file, sessions can't be saved - try again, may only be a temporary problem");
17967  FileClose(InHandle);
17968  Utilities->CallLogPop(1401);
17969  return;
17970  }
17971  }
17972  int CountIn, CountOut;
17973  char *Buffer = new char[10000]; // can't use LoadFileString as that expects a '\0' delimiter
17974 
17975  while(true)
17976  {
17977  CountIn = FileRead(InHandle, Buffer, 10000);
17978  CountOut = FileWrite(OutHandle, Buffer, CountIn);
17979  if(CountOut != CountIn)
17980  {
17981  ShowMessage("Error in writing to the temporary timetable file, sessions can't be saved - try again, may only be a temporary problem");
17982  delete Buffer;
17983  FileClose(InHandle);
17984  FileClose(OutHandle);
17985  Utilities->CallLogPop(1402);
17986  return;
17987  }
17988  if(CountIn < 10000)
17989  break;
17990  }
17991  delete Buffer;
17992  FileClose(InHandle);
17993  FileClose(OutHandle);
17994  Utilities->CallLogPop(1403);
17995 }
17996 
17997 // ---------------------------------------------------------------------------
17998 
17999 void TInterface::SetTrackLengths(int Caller, int Distance, int SpeedLimit) // Distance & SpeedLimit are -1 for no change to that parameter
18000 /*
18001  Rules: Platforms are fixed length elements of 100m and aren't changed - no, see note below. Variable length elements can't be less than 20m.
18002  above changed in v2.4.0 to be variable as other track, but if <50m or >200m a warning is given
18003 
18004  Enter with DistanceVector containing the PrefDir to be set, Distance containing the required sum of all element lengths,
18005  and SpeedLimit containing the speed limit. If either of these is -1 (can be -1 separately) then no change is to be made to it.
18006  Return for an empty DistanceVector. Deal first with a single element in the vector, giving a message if there is a platform there.
18007  Now set exit link position (XLinkPos) value for the first element in DistanceVector by checking which link connects to the second
18008  element in the vector, and give a warning message if fail to find it. Now have to make two passes through the vector, firstly to
18009  sum the fixed lengths, count the number of variable length elements and set the speed limit, and secondly to set the lengths.
18010  Firstly store the first XLinkPos so don't have to recalculate it for the second pass. On the first pass examine each element,
18011  incrementing the variable element count or summing the fixed length count as go along, and setting the speed limits providing
18012  SpeedLimit isn't -1. If Distance was -1 then still go through but don't count anything, just set the speed limits. Recalculate
18013  the next XLinkPos for each succeeding element.
18014  After the first pass return if Distance was -1 as in that case have now finished. Otherwise check if the distance to be set is less than
18015  the minimum possible within the rules, and if so give a message and return. Also give a warning message if there aren't any variable length
18016  elements. Now enter the second pass. In this the length of each variable element is set to int(RemainingDistance/RemainingVarElements) and
18017  fixed length elements are ignored. After each variable length element is set the RemainingDistance and RemainingVarElements are recalculated
18018  ready for the next setting. In this way there is never more than 1 difference between any two variable length elements and the total
18019  distance sums exactly to the value required. A check is made after every variable length element has been set to see whether RemainingDistance
18020  and RemainingVarElements are zero, and if they don't reach zero together (which they should after the last variable length element has
18021  been set), an error message is given.
18022 */
18023 
18024 {
18025  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLengths," + AnsiString(Distance) + "," + AnsiString(SpeedLimit));
18026  bool FoundFlag;
18027 
18028 // ResetDistanceElements(4);
18029  if(ConstructPrefDir->PrefDirSize() == 0)
18030  {
18031  Utilities->CallLogPop(608);
18032  return;
18033  }
18034 // must have PrefDir size of at least 2
18035 
18036 // first pass to count number of variable length elements, sum fixed lengths & set speed limit
18037 // for version in v2.4.0 have no fixed length elements but leave code as is as much as possible
18038  int VarElements = 0; // FixedLength = 0; drop this in v2.4.0
18039  bool NamedLocPresent = false;
18040 
18041  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
18042  {
18043  TPrefDirElement PrefDirElement = ConstructPrefDir->GetFixedPrefDirElementAt(167, x);
18044  TTrackElement & TE = Track->TrackElementAt(34, Track->GetVectorPositionFromTrackMap(28, PrefDirElement.HLoc, PrefDirElement.VLoc, FoundFlag));
18045  if(!FoundFlag)
18046  {
18047  throw Exception("Error - failed to find track element at " + AnsiString(TE.HLoc) + " & " + AnsiString(TE.VLoc) + " in SetLengths");
18048  }
18049  if((Distance != -1) && (!Track->IsPlatformOrNamedNonStationLocationPresent(2, TE.HLoc, TE.VLoc)))
18050  VarElements++;
18051  else if((Distance != -1) && (Track->IsPlatformOrNamedNonStationLocationPresent(3, TE.HLoc, TE.VLoc)))
18052  {
18053  VarElements++; // added in v2.4.0 for no fixed elements
18054  NamedLocPresent = true;
18055 // FixedLength+= DefaultTrackLength; dropped in v2.4.0 for no fixed elements
18056  }
18057 
18058  if((PrefDirElement.GetELinkPos() < 2) && (PrefDirElement.GetXLinkPos() < 2)) // could be points
18059  {
18060  if(SpeedLimit != -1)
18061  TE.SpeedLimit01 = SpeedLimit;
18062  }
18063  else
18064  {
18065  if(SpeedLimit != -1)
18066  TE.SpeedLimit23 = SpeedLimit;
18067  }
18068  }
18069  if(Distance == -1) // can't return before this as need to set speed limits
18070  {
18071  Utilities->CallLogPop(612);
18072  return;
18073  }
18074 
18075  if((NamedLocPresent) && (VarElements > 0) && ((Distance / VarElements) < 50)) // these two additions are for in v2.4.0
18076  {
18077  ShowMessage("Note: Named location elements are quite short. If they are too short the simulation might depart too far from reality.");
18078  }
18079 
18080  if((NamedLocPresent) && (VarElements > 0) && ((Distance / VarElements) > 200))
18081  {
18082  ShowMessage("Note: Named location elements are quite long. If they are too long the simulation might depart too far from reality.");
18083  }
18084 
18085 /* if(NamedLocPresent) as was
18086  {
18087  ShowMessage("Named location lengths won't be changed");
18088  }
18089 */
18090 
18091  if((VarElements * 20) > Distance) // removed '+ FixedLength'
18092  {
18093  ShowMessage("Required distance is less than the minimum, will set each element to the minimum (20m)");
18094  Distance = (VarElements * 20); // removed '+ FixedLength'
18095  }
18096  if(VarElements == 0)
18097  {
18098 // ShowMessage("Unable to set distance as all elements are of fixed length"); as was
18099  ShowMessage("No elements selected"); // probably don't need this but include for safety
18100  Utilities->CallLogPop(613);
18101  return;
18102  }
18103 
18104 // second pass, set variable lengths
18105  int RemainingDistance = Distance, RemainingVarElements = VarElements, NextLength = RemainingDistance / VarElements; // removed ' - FixedLength'
18106 
18107  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
18108  {
18109  TPrefDirElement PrefDirElement = ConstructPrefDir->GetFixedPrefDirElementAt(168, x);
18110  TTrackElement & TE = Track->TrackElementAt(35, Track->GetVectorPositionFromTrackMap(29, PrefDirElement.HLoc, PrefDirElement.VLoc, FoundFlag));
18111 // if(!Track->IsPlatformOrNamedNonStationLocationPresent(4, TE.HLoc, TE.VLoc)) //variable lengths dropped in v2.4.0
18112 // {
18113  if(NextLength < 20)
18114  NextLength = 20; // added for safety
18115  if(TE.TrackType == Points)
18116  {
18117  if((PrefDirElement.GetELinkPos() == 1) || (PrefDirElement.GetXLinkPos() == 1))
18118  {
18119  TE.Length01 = NextLength;
18120  }
18121  else
18122  {
18123  TE.Length23 = NextLength;
18124  }
18125  }
18126  else
18127  {
18128  if(PrefDirElement.GetELinkPos() < 2)
18129  {
18130  TE.Length01 = NextLength;
18131  }
18132  else
18133  {
18134  TE.Length23 = NextLength;
18135  }
18136  }
18137  RemainingDistance -= NextLength;
18138  RemainingVarElements--;
18139  if(RemainingVarElements > 0)
18140  NextLength = RemainingDistance / RemainingVarElements;
18141  else
18142  NextLength = 20;
18143 
18144 /* removed these as using integer division & that sometimes problematic. None of these errors ever reported but be safe
18145  if((RemainingDistance == 0) && (RemainingVarElements != 0))
18146  {
18147  throw Exception("Error RemainingDistance == 0 & RemainingVarElements != 0");
18148  }
18149  if((RemainingDistance != 0) && (RemainingVarElements == 0))
18150  {
18151  throw Exception("Error RemainingDistance != 0 & RemainingVarElements == 0");
18152  }
18153 */
18154 // }
18155  }
18156  Utilities->CallLogPop(614);
18157 }
18158 
18159 // ---------------------------------------------------------------------------
18160 
18162 {
18163  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveAsSubroutine");
18165  ShowMessage("Nothing to save!");
18166  else
18167  {
18168  if(Track->IsReadyForOperation())
18169  {
18170  SaveRailwayDialog->Filter = "Development file (*.dev)|*.dev|Railway file (*.rly)|*.rly";
18171  }
18172  else
18173  SaveRailwayDialog->Filter = "Development file (*.dev)|*.dev";
18174  if(SaveRailwayDialog->Execute())
18175  {
18176  if(SaveRailwayDialog->InitialDir != TPath::GetDirectoryName(SaveRailwayDialog->FileName))//new at v2.6.0 to retain a new directory
18177  {
18178  SaveRailwayDialog->InitialDir = TPath::GetDirectoryName(SaveRailwayDialog->FileName);
18179  LoadRailwayDialog->InitialDir = TPath::GetDirectoryName(SaveRailwayDialog->FileName);
18180  }
18181  Screen->Cursor = TCursor(-11); // Hourglass;
18182  TrainController->LogEvent("Save " + SaveRailwayDialog->FileName);
18183  AnsiString Extension = "";
18184  if(SaveRailwayDialog->FileName.Length() > 2)
18185  {
18186  Extension = AnsiString(SaveRailwayDialog->FileName).SubString(AnsiString(SaveRailwayDialog->FileName).Length() - 2, 3).UpperCase();
18187  }
18188  if((Extension == "DEV") || (Track->IsReadyForOperation() && (Extension == "RLY")))
18189  {
18190  std::ofstream VecFile(AnsiString(SaveRailwayDialog->FileName).c_str());
18191  if(!(VecFile.fail()))
18192  {
18196  // save track elements
18197  if(Track->UserGraphicVector.empty())
18198  {
18199  Track->SaveTrack(1, VecFile, false); // false for no graphics (**Active elements** saved as marker)
18200  }
18201  else
18202  {
18203  Track->SaveTrack(13, VecFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
18204  }
18205  // save text elements
18206  TextHandler->SaveText(1, VecFile);
18207  // save PrefDir elements
18208  EveryPrefDir->SavePrefDirVector(1, VecFile);
18209  if(!Track->UserGraphicVector.empty())
18210  {
18211  // save user graphics
18212  Track->SaveUserGraphics(4, VecFile);
18213  }
18214  VecFile.close();
18215  SavedFileName = SaveRailwayDialog->FileName; // includes the full PrefDir
18216  if(SavedFileName != "") // shouldn't be "" at this stage but leave in as a safeguard
18217  {
18218  char LastChar = SavedFileName[SavedFileName.Length()];
18219  if((LastChar == 'y') || (LastChar == 'Y'))
18220  {
18221  RlyFile = true;
18222  }
18223  else
18224  {
18225  RlyFile = false;
18226  }
18227  }
18228  else
18229  {
18230  RlyFile = false;
18231  }
18232  FileChangedFlag = false;
18233  for(int x = SaveRailwayDialog->FileName.Length(); x > 0; x--)
18234  {
18235  if(SaveRailwayDialog->FileName[x] == '\\')
18236  {
18237  RailwayTitle = SaveRailwayDialog->FileName.SubString(x + 1, SaveRailwayDialog->FileName.Length() - x - 4);
18238  // TimetableTitle = ""; leave this as is, no need to unload a tt just because saved railway
18239  SetCaption(7);
18240  break;
18241  }
18242  }
18243  Level1Mode = BaseMode;
18244  SetLevel1Mode(13); // to disable the save option
18245  } // if(!(VecFile.fail()))
18246  else
18247  ShowMessage("File open failed prior to save");
18248  } // else following if(!Track->IsReadyForOperation() && (Extension != "DEV"))
18249  else
18250  {
18251  ShowMessage("Can't save: extension must be either '.dev', or '.rly' with railway ready for operation");
18252  }
18253  Screen->Cursor = TCursor(-2); // Arrow
18254  } //if(SaveRailwayDialog->Execute())
18255  }
18256  Utilities->CallLogPop(1546);
18257 }
18258 
18259 // ---------------------------------------------------------------------------
18260 
18262 { // no need for caller or log as only setting values
18263  CutMenuItem->Visible = true;
18264  CopyMenuItem->Visible = true;
18265  FlipMenuItem->Visible = true;
18266  MirrorMenuItem->Visible = true;
18267  RotRightMenuItem->Visible = true;
18268  RotLeftMenuItem->Visible = true;
18269  RotateMenuItem->Visible = true;
18270  PasteMenuItem->Visible = true;
18271 // PasteWithAttributesMenuItem->Visible = true; //added at v2.2.0
18272  DeleteMenuItem->Visible = true;
18273  SelectLengthsMenuItem->Visible = true;
18274  ReselectMenuItem->Visible = true;
18275 
18276  CutMenuItem->Enabled = false;
18277  CopyMenuItem->Enabled = false;
18278  FlipMenuItem->Enabled = false;
18279  MirrorMenuItem->Enabled = false;
18280  RotRightMenuItem->Enabled = false;
18281  RotLeftMenuItem->Enabled = false;
18282  RotateMenuItem->Enabled = false;
18283  PasteMenuItem->Enabled = false;
18284 // PasteWithAttributesMenuItem->Enabled = false; //new at v2.2.0
18285  DeleteMenuItem->Enabled = false;
18286  SelectLengthsMenuItem->Enabled = false;
18287  if(SelectionValid)
18288  ReselectMenuItem->Enabled = true;
18289  else
18290  ReselectMenuItem->Enabled = false;
18291 
18292  SelectBiDirPrefDirsMenuItem->Visible = false;
18293  CancelSelectionMenuItem->Enabled = true;
18294  SelectMenuItem->Enabled = true;
18295 
18296  if(NoRailway())
18297  {
18298  EditMenu->Enabled = false;
18299  }
18300  else
18301  EditMenu->Enabled = true;
18302 }
18303 
18304 // ---------------------------------------------------------------------------
18305 
18307 { // no need for caller or log as only setting values
18308  EditMenu->Enabled = true;
18309 
18310  CutMenuItem->Visible = false;
18311  CopyMenuItem->Visible = false;
18312  FlipMenuItem->Visible = false;
18313  MirrorMenuItem->Visible = false;
18314  RotRightMenuItem->Visible = false;
18315  RotLeftMenuItem->Visible = false;
18316  RotateMenuItem->Visible = false;
18317  PasteMenuItem->Visible = false;
18318 // PasteWithAttributesMenuItem->Visible = false; //added at v2.2.0
18319  DeleteMenuItem->Visible = false;
18320  SelectLengthsMenuItem->Visible = false;
18321  ReselectMenuItem->Visible = false;
18322 
18323  SelectBiDirPrefDirsMenuItem->Visible = true;
18324  SelectBiDirPrefDirsMenuItem->Enabled = false;
18325  CancelSelectionMenuItem->Enabled = true;
18326  SelectMenuItem->Enabled = true;
18327 }
18328 
18329 // ---------------------------------------------------------------------------
18330 
18332 {
18333  return ((Track->NoActiveOrInactiveTrack(5)) && (TextHandler->TextVectorSize(8) == 0) && Track->UserGraphicVector.empty());
18334 }
18335 
18336 // ---------------------------------------------------------------------------
18337 
18339 {
18340  SelectRect.left = 0;
18341  SelectRect.right = 0;
18342  SelectRect.top = 0;
18343  SelectRect.bottom = 0;
18344 }
18345 
18346 // ---------------------------------------------------------------------------
18347 
18348 bool TInterface::EraseLocationNameText(int Caller, AnsiString Name, int &HPos, int &VPos)
18349 { // return position of erased name in HPos & VPos, return true for found & erased
18350  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",EraseLocationNameText," + Name);
18351  bool TextFound = false;
18352 
18353 // if(Track->LocationNameMultiMap.find(Name) == Track->LocationNameMultiMap.end()) {} //name not in LocationNameMultiMap, so don't erase from TextVector //condition dropped at v1.1.4 because of change in EnterLocationNames
18354 /* else */ if(TextHandler->FindText(0, Name, HPos, VPos))
18355  {
18356  if(TextHandler->TextErase(4, HPos, VPos, Name))
18357  {;
18358  } // condition not used
18359  TextFound = true;
18360  }
18361  Utilities->CallLogPop(1956);
18362  return TextFound;
18363 }
18364 
18365 // ---------------------------------------------------------------------------
18366 
18367 void TInterface::AddLocationNameText(int Caller, AnsiString Name, int HPos, int VPos, bool UseEnteredPosition)
18368 {
18369  if(Name == "")
18370  {
18371  return;
18372  }
18373  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",AddLocationNameText," + Name + "," + AnsiString(HPos) + "," +
18374  AnsiString(VPos) + "," + AnsiString((short)UseEnteredPosition));
18375  int VPosHi, VPosLo, TextPosHi, TextPosLo;
18376  TFont *Font = Display->GetFont();
18377 
18378  if(!UseEnteredPosition)
18379  {
18380  if(!Track->FindHighestLowestAndLeftmostNamedElements(0, Name, VPosHi, VPosLo, HPos))
18381  {
18382  Utilities->CallLogPop(1561);
18383  return;
18384  }
18385  int Depth = abs(Font->Height); // Height may be negative - see C++Builder Help file
18386  TextPosHi = VPosHi + 20; // add depth of track element + 4 pixels
18387  TextPosLo = VPosLo - Depth - 4; // reduce by depth of font + 4 pixels
18388  int ScreenPosHi = (Display->DisplayOffsetV * 16) + 576;
18389  int ScreenPosLo = Display->DisplayOffsetV * 16;
18390  if(TextPosLo >= ScreenPosLo)
18391  VPos = TextPosLo; // if Lo value on screen then use that - displays above the location
18392  else if(TextPosHi < ScreenPosHi)
18393  VPos = TextPosHi;
18394  else
18395  VPos = ScreenPosLo + 288; // if location extends to or beyond height of screen the display in centre of screen
18396  }
18397  TTextItem TI(HPos, VPos, Name, Font);
18398 
18399  TI.Font = Font; // may have been changed in constructor when returned as reference
18400  TextHandler->EnterAndDisplayNewText(1, TI, HPos, VPos);
18401  Utilities->CallLogPop(1558);
18402 }
18403 
18404 // ---------------------------------------------------------------------------
18405 
18407 {
18408  try
18409  {
18410 /*
18411  ShowMessage(
18412  "Interface->Left + Interface->Width " + UnicodeString(Interface->Left + Interface->Width) +
18413  "\nInterface->Left + MainScreen->Left + MainScreen->Width " +
18414  UnicodeString(Interface->Left + MainScreen->Left + MainScreen->Width) +
18415  "\n\nMainScreen->Width " + UnicodeString(MainScreen->Width) +
18416  "\nMainScreen->Height " + UnicodeString(MainScreen->Height) +
18417  "\nMainScreen->Top " + UnicodeString(MainScreen->Top) +
18418  "\nMainScreen->Left " + UnicodeString(MainScreen->Left) +
18419  " Right " + UnicodeString(MainScreen->Width + MainScreen->Left) +
18420  "\n\nInterface->Width " + UnicodeString(Interface->Width) +
18421  "\nInterface->Left " + UnicodeString(Interface->Left) +
18422  "\nInterface->Top " + UnicodeString(Interface->Top) +
18423  "\n\nScreenRightButton->Left " + UnicodeString(ScreenRightButton->Left)
18424  );
18425 */
18426 /*
18427  for(unsigned int x=0; x<TrainController->TrainVector.size(); x++)
18428  {
18429  if((TrainController->TrainVectorAt(-1, x).HeadCode == "2K02") && (!TrainController->TrainVectorAt(-1, x).TrainOnContinuation(-1)))
18430  {
18431  TrainController->TrainVectorAt(-1, x).TrainFailurePending = true;
18432  }
18433  }
18434 */
18435 
18436 // throw Exception("Test error"); //generate an error file
18437 
18438 // ShowMessage("MissedTicks = " + AnsiString(MissedTicks) + "; TotalTicks = " + AnsiString(TotalTicks));
18439 
18440  }
18441  catch(const Exception &e)
18442  {
18443  ErrorLog(114, e.Message);
18444  }
18445 }
18446 
18447 // ---------------------------------------------------------------------------
18448 /*
18449  void TInterface::LoadNormalSignalGlyphs(int Caller) //changed - see below
18450  {
18451  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadNormalSignalGlyphs,");
18452  SpeedButton68->Glyph->LoadFromResourceName(0, "gl68"); SpeedButton69->Glyph->LoadFromResourceName(0, "gl69");
18453  SpeedButton70->Glyph->LoadFromResourceName(0, "gl70"); SpeedButton71->Glyph->LoadFromResourceName(0, "gl71");
18454  SpeedButton72->Glyph->LoadFromResourceName(0, "gl72"); SpeedButton73->Glyph->LoadFromResourceName(0, "gl73");
18455  SpeedButton74->Glyph->LoadFromResourceName(0, "gl74"); SpeedButton75->Glyph->LoadFromResourceName(0, "gl75");
18456  Utilities->CallLogPop(**);
18457  }
18458 
18459  //---------------------------------------------------------------------------
18460 
18461  void TInterface::LoadGroundSignalGlyphs(int Caller) //changed - see below
18462  {
18463  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadGroundSignalGlyphs,");
18464  SpeedButton68->Glyph->LoadFromResourceName(0, "bm68grounddblred"); SpeedButton69->Glyph->LoadFromResourceName(0, "bm69grounddblred");
18465  SpeedButton70->Glyph->LoadFromResourceName(0, "bm70grounddblred"); SpeedButton71->Glyph->LoadFromResourceName(0, "bm71grounddblred");
18466  SpeedButton72->Glyph->LoadFromResourceName(0, "bm72grounddblred"); SpeedButton73->Glyph->LoadFromResourceName(0, "gl73grounddblred");
18467  SpeedButton74->Glyph->LoadFromResourceName(0, "gl74grounddblred"); SpeedButton75->Glyph->LoadFromResourceName(0, "bm75grounddblred");
18468  Utilities->CallLogPop(**);
18469  }
18470 */
18471 // ---------------------------------------------------------------------------
18472 void TInterface::LoadNormalSignalGlyphs(int Caller) // changed from the above at v2.3.0 so the signal glyphs change hands
18473 {
18474  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadNormalSignalGlyphs,");
18483  Utilities->CallLogPop(1871);
18484 }
18485 
18486 // ---------------------------------------------------------------------------
18487 
18488 void TInterface::LoadGroundSignalGlyphs(int Caller) // changed from the above at v2.3.0 so the signal glyphs change hands
18489 {
18490  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadGroundSignalGlyphs,");
18499  Utilities->CallLogPop(1872);
18500 }
18501 
18502 // ---------------------------------------------------------------------------
18503 
18504 void TInterface::UpdateOperatorActionPanel(int Caller) // new at v2.2.0
18505  // limit it to 20 entries max
18506 {
18507  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",UpdateOperatorActionPanel");
18509  {
18510  OAListBox->Clear();
18511  }
18513  // new at v2.2.0
18514  {
18515  Utilities->CallLogPop(2092);
18516  return;
18517  }
18518  AnsiString OpTimeToActDisplay;
18519  AnsiString OpTimeToActString;
18520  AnsiString HeadCode;
18521  float OpTimeToActFloat;
18522  TTrainController::THCandTrainPosParam HCandTrainPosParam;
18523 
18526  {
18527  if(OAListBox->Items->Count >= 20)
18528  {
18529  break;
18530  }
18531  OpTimeToActFloat = TrainController->OpTimeToActMultiMapIterator->first;
18532  HCandTrainPosParam = TrainController->OpTimeToActMultiMapIterator->second;
18533  HeadCode = HCandTrainPosParam.first;
18534  if(OpTimeToActFloat < 0.25) // 15 secs estimated
18535  {
18536  OpTimeToActString = "NOW";
18537  }
18538  else if(OpTimeToActFloat < 1)
18539  {
18540  OpTimeToActString = "<1";
18541  }
18542  else
18543  {
18544  OpTimeToActString = AnsiString(floor(OpTimeToActFloat));
18545  }
18546  if(OpTimeToActFloat < 60)
18547  {
18548  OpTimeToActDisplay = HeadCode + AnsiString('\t') + OpTimeToActString;
18549  OAListBox->Items->Add(OpTimeToActDisplay); // original
18550  }
18552  }
18553  Utilities->CallLogPop(2093);
18554 }
18555 
18556 // ---------------------------------------------------------------------------
18557 
18558 void TInterface::LoadUserGraphic(int Caller) // new at v2.4.0
18559 {
18560  try
18561  {
18562  TrainController->LogEvent("LoadUserGraphic");
18563  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadUserGraphic");
18564  if(LoadUserGraphicDialog->Execute())
18565  {
18566  TrainController->LogEvent("LoadUserGraphic " + LoadUserGraphicDialog->FileName);
18567  SelectedGraphicFileName = AnsiString(LoadUserGraphicDialog->FileName); // SelectedGraphicFileName is a class member
18569  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.find(SelectedGraphicFileName);
18570  if(UGMIt == Track->UserGraphicMap.end()) // i.e. there isn't an entry for that filename so insert one, else take no action
18571  {
18572  UGME.first = SelectedGraphicFileName;
18573  TPicture *PicPtr = new TPicture;
18574  PicPtr->LoadFromFile(SelectedGraphicFileName);
18575  UGME.second = PicPtr;
18576  if(!Track->UserGraphicMap.insert(UGME).second) // if no failure then the new entry is inserted
18577  {
18578  throw Exception("Map Insertion Error 1 - UserGraphicMap insertion failure for " + SelectedGraphicFileName);
18579  }
18580  }
18582  SetLevel2TrackMode(65);
18583  }
18584  Utilities->CallLogPop(2191);
18585  }
18586  catch(const EInvalidGraphic &e)
18587  {
18588  ShowMessage(
18589  "Incorrect file format, the file can't be loaded.\nEnsure that the file you want is a valid graphic file with extension .bmp, .gif, .jpg, or .png");
18590  }
18591  catch(const Exception &e)
18592  {
18593  ErrorLog(215, e.Message);
18594  }
18595 }
18596 
18597 // ---------------------------------------------------------------------------
18598 /*
18599  Problems with ifstream reading (see 'SessionFileIntegrityCheck(AnsiString FileName)' above):-
18600 
18601  These problems were with Borland C++Builder 4.
18602 
18603  The functions saved in OldFiles\Backups220809Duringifstream testing were used for testing the odd behaviour where the
18604  ifstream pointer gave different characters using get() and getline(), when reading the timetable entries in the session
18605  file for 20/08/09 at 18:45 (saved). All was well until point 48677 in the session file, when for some reason the
18606  getline(0 & get(0 gave different results. Many earlier timetable strings had been read OK before that, and it wasn't
18607  clear what was special about this particular string.
18608  Later more detailed study found that on reading the string beginning at point 48605 (i.e. the one earlier than above),
18609  within function CheckNoNewLineAtStartNonZeroTerminatedFileString the file pointer (using tellg()) reduced from 48606 to
18610  48604 after reading the 'F' character. Thereafter characters were read correctly but the pointer remained 2 too low.
18611  This is thought to be a flaw in the compiler.
18612  Later again additional tellg()s and a seekg()s were included in CheckNoNewLineAtStartNonZeroTerminatedFileString, and
18613  though these should have had no effect they somehow caused the next getline() within CheckTimetableFromSessionFile to
18614  read a null, even though the pointer had been reset to its value before the call to
18615  CheckNoNewLineAtStartNonZeroTerminatedFileString. Again this seems to be a flaw in the compiler, where the pointer
18616  that is indicated by tellg and the true pointer within the system can be different.
18617  Tried the old c++ stream library to see if that worked but it was exactly the same. Probably because the same code is
18618  used for both with the new library just defined within the std namespace.
18619  Success!! Traced to the putback function failing. It (apparently) can't be used if the file pointer has been altered
18620  after the last read that is to be put back. Corrected that & the most recent session file checked out & loaded OK.
18621  (note - don't need the ifstream file to be open in output mode for the putback to work)
18622  But: the earlier file - 18:45 as above - still fails to advance the file pointer in the middle of checking the
18623  timetable, it sticks at position 48601. This position points to 'r' in 'Frh' just before a newline. Also the file
18624  integrity is OK up to and after this sticking point. Oddly though the loading function works fine (i.e. by bypassing
18625  the integrity check function), though the timetable isn't read directly, it is copied to a new stand-alone timetable
18626  file and that read by the program.
18627  Created a new version of CheckNoNewLineAtStartNonZeroTerminatedFileString with 'New' at end, & got rid of all the
18628  internal digressions & getlines. This passed the earlier sticking point, but stuck later at 48677, i.e. the 'h' from
18629  'Frh' at the end of the entry following that for the earlier sticking point. Here
18630  CheckNoNewLineAtStartNonZeroTerminatedFileStringNew works fine, with end pointer correctly set at 48680, i.e. after the
18631  newline, but the subsequent getline() function, although it retrieves the line correctly, the file pointer is set to
18632  48677, i.e. before the newline, so getline seems to fail to extract the newline character. Still to check - why doesn't
18633  CheckNoNewLineAtStartNonZeroTerminatedFileStringNew see 'h' instead of '0' in the subsequent read? If it did the two
18634  would tally, though would still be wrong.
18635  Further investigation:- CheckNoNewLineAtStartNonZeroTerminatedFileStringNew doesn't seem to recognize the file pointer
18636  as set by seekg at 48677. It continues to read at the point it left off earlier, whereas getline() does read at 48677
18637  & recovers 'h'. Continuing to apply getline() after the above effect it is found that it doesn't extract newlines after
18638  reading further lines, but extracts them when read alone i.e. it reads a line then a null in succession, although the
18639  lines are only separated by single newline characters.
18640 
18641  Need to check:
18642  1. Does the file read correctly if only get() functions used without getline() and without resetting the file pointer?
18643  2. Does the file read correctly if only getline() functions used without get() and without resetting the file pointer?
18644  3. Does the file read correctly if get() functions alternated with getline() but without resetting the file pointer?
18645 
18646  For 1: Still goes wrong at usual place, reads 'h' at the same point. Try not resetting the file pointer with seekg.
18647  Tried this - got past the earlier point but failed later with a reduction in file pointer after a character read. In
18648  fact the reduction was by 40 bytes for reading a single comma! Try without any tellg's - yes, that got past all the
18649  timetable OK. So, works OK with just get() providing no tellg's (& no seekg's).
18650 
18651  For 2: Works OK using getline().
18652 
18653  For 3: Gets to end of timetable OK but the next tellg gives a wrong value. Check if using getline() alone gives a
18654  wrong tellg. Tried getline() alone, reached end of TT as before, but gave the same wrong file pos on using tellg.
18655  Try continuing to see if works OK in spite of tellg giving wrong result. Yes it works OK. Hence the problem seems to
18656  be tellg, which sometimes returns wrong results, and they corrupt things when used in seekg.
18657 
18658  Overall conclusion: Avoid all tellg's & seekg's. If need to reset a file position then close and reopen it.
18659 */
18660 
18661 // ---------------------------------------------------------------------------
18662 
TAllRoutes::TrackIsInARoute
bool TrackIsInARoute(int Caller, int TrackVectorPosition, int LinkPos)
Examines Route2MultiMap and if the element at TrackVectorPosition with LinkPos (can be entry or exit)...
Definition: TrackUnit.cpp:16104
TInterface::SpeedButton59
TSpeedButton * SpeedButton59
Definition: InterfaceUnit.h:563
TInterface::CopyTTEntryButtonClick
void __fastcall CopyTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3622
TInterface::CtrlKey
bool CtrlKey
true when the CTRL key is pressed (see also ShiftKey)
Definition: InterfaceUnit.h:933
TInterface::MTBFEditBox
TEdit * MTBFEditBox
Definition: InterfaceUnit.h:481
TOnePrefDir::LastElementPtr
TPrefDirVectorIterator LastElementPtr(int Caller)
Return a pointer to the last element in the vector.
Definition: TrackUnit.cpp:10220
TInterface::ScreenLeftButtonClick
void __fastcall ScreenLeftButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8371
TInterface::ExitMenuItem
TMenuItem * ExitMenuItem
Definition: InterfaceUnit.h:417
TTrain::AllowedToPassRedSignal
bool AllowedToPassRedSignal
set when train has been called on, or when under signaller control and instructed to pass a red signa...
Definition: TrainUnit.h:339
TInterface::TextMoveVPos
int TextMoveVPos
used to store the original text 'H' & 'V' positions for use during text moving
Definition: InterfaceUnit.h:1098
TInterface::OperMode
@ OperMode
Definition: InterfaceUnit.h:851
TTrain::ZeroPowerNoNewShuttleFromNonRepeatMessage
bool ZeroPowerNoNewShuttleFromNonRepeatMessage
Definition: TrainUnit.h:306
TInterface::SpeedButton140
TSpeedButton * SpeedButton140
Definition: InterfaceUnit.h:644
TTrain::ZeroPowerNoNewServiceMessage
bool ZeroPowerNoNewServiceMessage
Definition: TrainUnit.h:305
TUserGraphicItem::UserGraphic
TPicture * UserGraphic
Definition: DisplayUnit.h:36
TTrack::UserGraphicVectorAt
TUserGraphicItem & UserGraphicVectorAt(int Caller, int At)
A range-checked version of UserGraphicVector.at(At)
Definition: TrackUnit.cpp:10193
TInterface::AddPrefDirButton
TBitBtn * AddPrefDirButton
Definition: InterfaceUnit.h:116
TInterface::RemoveTrainMenuItem
TMenuItem * RemoveTrainMenuItem
Definition: InterfaceUnit.h:467
TInterface::LocationNamesSetImage
TImage * LocationNamesSetImage
Definition: InterfaceUnit.h:278
TInterface::SpeedLimitBox
TEdit * SpeedLimitBox
distance/speed setting edit box that accepts speed limits
Definition: InterfaceUnit.h:92
TTextItem::VPos
int VPos
the vertical position on the railway
Definition: TextUnit.h:50
TInterface::SaveImageAndGridMenuItemClick
void __fastcall SaveImageAndGridMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2600
TDisplay::DisplayOffsetHHome
static int DisplayOffsetHHome
the horizontal offset of the 'Home' display
Definition: DisplayUnit.h:80
TTrainController
Handles all train and timetable activities, only one object created.
Definition: TrainUnit.h:630
TInterface::FloatingInfoMenu
TMenuItem * FloatingInfoMenu
Definition: InterfaceUnit.h:443
TInterface::SpeedButton34
TSpeedButton * SpeedButton34
Definition: InterfaceUnit.h:538
TInterface::NewTTEntryKeyFlag
bool NewTTEntryKeyFlag
Definition: InterfaceUnit.h:1020
TInterface::ConflictAnalysisButtonClick
void __fastcall ConflictAnalysisButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12325
TInterface::CallingOnButton
TSpeedButton * CallingOnButton
Definition: InterfaceUnit.h:205
TInterface::BuildTrainDataVectorForValidateFile
bool BuildTrainDataVectorForValidateFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway)
Check the integrity of a stored timetable file (either as a stand alone file or within a session file...
Definition: InterfaceUnit.cpp:16973
TInterface::SpeedButton42
TSpeedButton * SpeedButton42
Definition: InterfaceUnit.h:546
TInterface::SelectBitmapMouseLocX
int SelectBitmapMouseLocX
when flag SelectPickedUp is set to true (see above - to allow a selected screen area to move during M...
Definition: InterfaceUnit.h:1074
TInterface::PrefDirPanel
TPanel * PrefDirPanel
'Set preferred directions' panel
Definition: InterfaceUnit.h:359
TInterface::PrefDirPanelLabel
TLabel * PrefDirPanelLabel
label to the left of PrefDirPanel
Definition: InterfaceUnit.h:305
TOnePrefDir::RebuildPrefDirVector
void RebuildPrefDirVector(int Caller)
Called after the track vector has been rebuilt following linking, to rebuild the preferred direction ...
Definition: TrackUnit.cpp:11675
TInterface::MTBFEditBoxKeyUp
void __fastcall MTBFEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:12140
TInterface::TrackMode
@ TrackMode
Definition: InterfaceUnit.h:851
TOneRoute::GetPreferredRouteStartElement
bool GetPreferredRouteStartElement(int Caller, int HLoc, int VLoc, TOnePrefDir *EveryPrefDir, bool ConsecSignalsRoute, bool AutoSigsFlag)
Set the starting conditions for a preferred direction or automatic signal route selection beginning o...
Definition: TrackUnit.cpp:12764
TAllRoutes::LockedRouteVector
TLockedRouteVector LockedRouteVector
the vector that stores all the locked routes on the railway
Definition: TrackUnit.h:1582
TInterface::SaveSessionButton
TBitBtn * SaveSessionButton
Definition: InterfaceUnit.h:201
TInterface::TTLabel2
TLabel * TTLabel2
Definition: InterfaceUnit.h:340
TInterface::TTClockx1ButtonClick
void __fastcall TTClockx1ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11743
TUtilities::LoadFileString
AnsiString LoadFileString(std::ifstream &InFile)
loads a string value from the file
Definition: Utilities.cpp:182
TInterface::LengthConversionPanel
TPanel * LengthConversionPanel
Definition: InterfaceUnit.h:105
TInterface::SpeedButton143
TSpeedButton * SpeedButton143
Definition: InterfaceUnit.h:647
TInterface::ChangeDirectionMenuItem
TMenuItem * ChangeDirectionMenuItem
Definition: InterfaceUnit.h:462
TTrack::AnyLinkedLevelCrossingElementsWithRoutesOrTrains
bool AnyLinkedLevelCrossingElementsWithRoutesOrTrains(int Caller, int HLoc, int VLoc, bool &TrainPresent)
True if a route or train present on any linked level crossing element.
Definition: TrackUnit.cpp:6713
TTrain::MidEntryPos
int MidEntryPos
Definition: TrainUnit.h:327
TTrainController::RebuildOpTimeToActMultimap
void RebuildOpTimeToActMultimap(int Caller)
new v2.2.0 for OperatorActionPanel
Definition: TrainUnit.cpp:17352
TTrainController::PwrHigh
bool PwrHigh
Definition: TrainUnit.h:738
TInterface::StepForwardMenuItem
TMenuItem * StepForwardMenuItem
Definition: InterfaceUnit.h:465
TTrack::SelectGraphicVector
TUserGraphicVector SelectGraphicVector
Definition: TrackUnit.h:702
TFixedTrackPiece::GraphicPtr
Graphics::TBitmap * GraphicPtr
the track bitmap for display on the zoomed-in railway
Definition: TrackUnit.h:90
SignallerMoveForwards
@ SignallerMoveForwards
Definition: TrainUnit.h:50
TInterface::SignallerControlStopMenuItem
TMenuItem * SignallerControlStopMenuItem
Definition: InterfaceUnit.h:466
TRailGraphics::ConvertSignalsToOppositeHand
void ConvertSignalsToOppositeHand(int Caller)
Converts all signal graphics to opposite hand new at v2.3.0.
Definition: GraphicUnit.cpp:4307
TInterface::FormResize
void __fastcall FormResize(TObject *Sender)
Definition: InterfaceUnit.cpp:11994
TInterface::SpeedButton70
TSpeedButton * SpeedButton70
Definition: InterfaceUnit.h:574
TInterface::SpeedButton144
TSpeedButton * SpeedButton144
Definition: InterfaceUnit.h:648
TInterface::SpeedButton32
TSpeedButton * SpeedButton32
Definition: InterfaceUnit.h:536
TInterface::SaveTTAsButtonClick
void __fastcall SaveTTAsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4091
TInterface::SelectBitmapHLoc
int SelectBitmapHLoc
the original (prior to moving & after finished moving) HLoc value of Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1072
TInterface::OperatorActionButton
TBitBtn * OperatorActionButton
Definition: InterfaceUnit.h:202
TInterface::DistanceKey
TImage * DistanceKey
information panel displayed when setting distances & speed limits
Definition: InterfaceUnit.h:268
AboutUnit.h
Arrive
@ Arrive
Definition: TrainUnit.h:49
TInterface::OperatorActionPanelDragStartX
int OperatorActionPanelDragStartX
mouse 'X' position when the OperatorActionPanel begins to be dragged
Definition: InterfaceUnit.h:1060
TInterface::SpeedButton54
TSpeedButton * SpeedButton54
Definition: InterfaceUnit.h:558
TInterface::PasteWarningSentFlag
bool PasteWarningSentFlag
indicates that the warning message about pasting overwriting the area has been given,...
Definition: InterfaceUnit.h:955
TInterface::StartWholeRailwayMoveVPos
int StartWholeRailwayMoveVPos
mouse Y position when start to move the whole railway
Definition: InterfaceUnit.h:1084
TTrain::ZeroPowerNoCDTMessage
bool ZeroPowerNoCDTMessage
Definition: TrainUnit.h:304
TTrain::CallingOnFlag
bool CallingOnFlag
calling on permitted
Definition: TrainUnit.h:345
TInterface::UnrestrictedButton
TBitBtn * UnrestrictedButton
Definition: InterfaceUnit.h:197
TTrack::UserGraphicMap
TUserGraphicMap UserGraphicMap
the map of graphic filenames as key and TPicture* as values
Definition: TrackUnit.h:703
TRailGraphics::SpeedBut72NormBlackGlyph
Graphics::TBitmap * SpeedBut72NormBlackGlyph
Definition: GraphicUnit.h:1048
TOnePrefDir::CheckPrefDirAgainstTrackVector
void CheckPrefDirAgainstTrackVector(int Caller)
Check loaded PrefDir against loaded track, and if discrepancies found give message & clear EveryPrefD...
Definition: TrackUnit.cpp:11715
TInterface::ExportTTMenuItemClick
void __fastcall ExportTTMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3007
TInterface::RestoreTTKeyFlag
bool RestoreTTKeyFlag
Definition: InterfaceUnit.h:1026
TInterface::CancelSelectionMenuItemClick
void __fastcall CancelSelectionMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9645
TRailGraphics::ChangeAllTransparentColours
void ChangeAllTransparentColours(TColor NewTransparentColour, TColor OldTransparentColour)
Definition: GraphicUnit.cpp:3579
TInterface::PERFLOG_DIR_NAME
static const UnicodeString PERFLOG_DIR_NAME
Definition: InterfaceUnit.h:864
TInterface::WholeRailwayMoving
bool WholeRailwayMoving
true when moving the railway with the mouse, new at v2.1.0
Definition: InterfaceUnit.h:1005
TOneRoute::GetNonPreferredRouteStartElement
bool GetNonPreferredRouteStartElement(int Caller, int HLoc, int VLoc, bool ConsecSignalsRoute, bool Callon)
Set the starting conditions for a non-preferred (i.e. unrestricted) route selection beginning on HLoc...
Definition: TrackUnit.cpp:14179
TInterface::TextFoundFlag
bool TextFoundFlag
indicates that a text item has been found when clicking on a build screen during 'AddText' or 'MoveTe...
Definition: InterfaceUnit.h:985
TInterface::DisableRouteButtons
void DisableRouteButtons(int Caller)
Called during operation whenever the route type buttons need to be disabled, e.g. when paused.
Definition: InterfaceUnit.cpp:17717
TInterface::OperateRailwayMenuItemClick
void __fastcall OperateRailwayMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2012
TInterface::DerailImage
TImage * DerailImage
Definition: InterfaceUnit.h:264
TTrain::MaxRunningSpeed
double MaxRunningSpeed
the current maximum train running speed
Definition: TrainUnit.h:383
TInterface::TTLabel3
TLabel * TTLabel3
Definition: InterfaceUnit.h:341
TTrack::BarriersDownVector
TActiveLCVector BarriersDownVector
vector of LCs with barriers down
Definition: TrackUnit.h:686
TPrefDirElement::GetXLinkPos
int GetXLinkPos() const
Returns the XLink array position.
Definition: TrackUnit.h:289
TRailGraphics::SpeedBut75NormBlackGlyph
Graphics::TBitmap * SpeedBut75NormBlackGlyph
Definition: GraphicUnit.h:1051
TTrack::IsLCBarrierDownAtHV
bool IsLCBarrierDownAtHV(int Caller, int HLoc, int VLoc)
True if an open (to trains) level crossing is found at H & V.
Definition: TrackUnit.cpp:6566
RestoreTimetableControl
@ RestoreTimetableControl
Definition: TrainUnit.h:50
TTrainController::LastSessionSaveTTClockTime
TDateTime LastSessionSaveTTClockTime
Definition: TrainUnit.h:641
TInterface::TTSelectedEntry
AnsiString TTSelectedEntry
used to record the current timetable entry when changing to AZ order or back to original order
Definition: InterfaceUnit.h:920
TUtilities::ScreenElementWidth
int ScreenElementWidth
width of display screen in elements
Definition: Utilities.h:48
TAllRoutes::AutoSigsRoute
@ AutoSigsRoute
Definition: TrackUnit.h:1512
TInterface::SpeedButton19
TSpeedButton * SpeedButton19
Definition: InterfaceUnit.h:523
TTrack::GetVectorPositionFromTrackMap
int GetVectorPositionFromTrackMap(int Caller, int HLoc, int VLoc, bool &FoundFlag)
Returns the track vector position corresponding to the Hloc & VLoc positions, FoundFlag indicates whe...
Definition: TrackUnit.cpp:5079
TTrack::GetTrackElementFromTrackMap
TTrackElement & GetTrackElementFromTrackMap(int Caller, int HLoc, int VLoc)
Return a reference to the element at HLoc & VLoc, if no element is found an error is thrown.
Definition: TrackUnit.cpp:5106
TActionVectorEntry::LocationType
TTimetableLocationType LocationType
indicates where the train is when the relevant action occurs
Definition: TrainUnit.h:112
TInterface::MasterClockTimer
void __fastcall MasterClockTimer(TObject *Sender)
Definition: InterfaceUnit.cpp:7694
TTrack::GapFlashGreenPosition
int GapFlashGreenPosition
Definition: TrackUnit.h:670
TInterface::MainScreen
TImage * MainScreen
the railway display screen
Definition: InterfaceUnit.h:285
TInterface::SpeedButton67
TSpeedButton * SpeedButton67
Definition: InterfaceUnit.h:571
NamedNonStationLocation
@ NamedNonStationLocation
Definition: TrackUnit.h:64
TInterface::CutMenuItem
TMenuItem * CutMenuItem
Definition: InterfaceUnit.h:432
TInterface::SpeedButton120
TSpeedButton * SpeedButton120
Definition: InterfaceUnit.h:624
TInterface::LCResetCounter
unsigned int LCResetCounter
count up to 20 then resets - to check LCs & raise barriers if no route & no train present
Definition: InterfaceUnit.h:1046
TInterface::BlueBgndMenuItem
TMenuItem * BlueBgndMenuItem
Definition: InterfaceUnit.h:427
TTrack::NoActiveTrack
bool NoActiveTrack(int Caller)
True if there is no active track in the railway.
Definition: TrackUnit.cpp:1645
TInterface::TTLabel1
TLabel * TTLabel1
Definition: InterfaceUnit.h:339
TTrack::CalcHLocMinEtc
void CalcHLocMinEtc(int Caller)
Examine TrackVector, InactiveTrackVector and TextVector, and set the values that indicate the extent ...
Definition: TrackUnit.cpp:9192
TInterface::ResetChangedFileDataAndCaption
void ResetChangedFileDataAndCaption(int Caller, bool NonPrefDirChangesMade)
Called whenever the railway is changed to deal with title displays (loaded railway and timetable) and...
Definition: InterfaceUnit.cpp:15821
TTrain::MaxBrakeRate
double MaxBrakeRate
the maximum brake rate that the train can achieve
Definition: TrainUnit.h:387
TInterface::SpeedButton52
TSpeedButton * SpeedButton52
Definition: InterfaceUnit.h:556
TInterface::IMAGE_DIR_NAME
static const UnicodeString IMAGE_DIR_NAME
Definition: InterfaceUnit.h:866
TInterface::ShowPerformancePanel
bool ShowPerformancePanel
true when the 'show performance panel' button has been clicked during operation
Definition: InterfaceUnit.h:979
TInterface::LoadSessionDialog
TOpenDialog * LoadSessionDialog
Definition: InterfaceUnit.h:489
TTextHandler::TextVector
TTextVector TextVector
Definition: TextUnit.h:69
TInterface::OutputLog10MouseDown
void __fastcall OutputLog10MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11115
TTrack::Lowering
@ Lowering
Definition: TrackUnit.h:523
TTrack::FindNonPlatformMatch
bool FindNonPlatformMatch(int Caller, int HLoc, int VLoc, int &Position, TTrackElement &TrackElement)
True if find a non-platform element at HLoc & VLoc, and if so return its TrackVector position and a r...
Definition: TrackUnit.cpp:2449
TInterface::SpeedButton116
TSpeedButton * SpeedButton116
Definition: InterfaceUnit.h:620
TTrack::MatchingPoint
bool MatchingPoint(int Caller, unsigned int TrackVectorPosition, unsigned int DivergingPosition)
Definition: TrackUnit.cpp:5235
TTrackElement::StationEntryStopLinkPos2
int StationEntryStopLinkPos2
Used for track at platforms and non-station named locations to mark the train front element stop posi...
Definition: TrackUnit.h:149
TTrain::MidExitPos
int MidExitPos
Definition: TrainUnit.h:327
TInterface::NewSelectBitmapVLoc
int NewSelectBitmapVLoc
as above for VLoc
Definition: InterfaceUnit.h:1058
TInterface::MoveTextOrGraphic
@ MoveTextOrGraphic
Definition: InterfaceUnit.h:881
TInterface::ScreenGridButton
TBitBtn * ScreenGridButton
Definition: InterfaceUnit.h:72
TTrack::EnterLocationName
void EnterLocationName(int Caller, AnsiString LocationName, bool AddingElements)
All platform, concourse, footcrossing & non-station named location elements are able to have a Locati...
Definition: TrackUnit.cpp:7356
TInterface::EditMenu
TMenuItem * EditMenu
Definition: InterfaceUnit.h:429
TTrain::TrainFailed
bool TrainFailed
added at v2.4.0 to indicate failure
Definition: TrainUnit.h:369
TUtilities::CheckFileStringZeroDelimiter
bool CheckFileStringZeroDelimiter(std::ifstream &InFile)
checks that the value is a string ('0' only accepted as the delimiter), returns true for success
Definition: Utilities.cpp:384
DisplayUnit.h
TInterface::ResetSelectRect
void ResetSelectRect()
SelectRect is the rectangle selected via the 'Edit'menu, and this function sets left,...
Definition: InterfaceUnit.cpp:18338
TInterface::TTClockAdjustWarningHide
bool TTClockAdjustWarningHide
true if user opts not to show the timetable clock adjustment warning (false on starting the program)
Definition: InterfaceUnit.h:987
TInterface::TTLabel9
TLabel * TTLabel9
Definition: InterfaceUnit.h:347
TTrain::ZeroPowerNoFrontSplitMessage
bool ZeroPowerNoFrontSplitMessage
Definition: TrainUnit.h:300
TTrainController::SPADWarning
bool SPADWarning
Definition: TrainUnit.h:724
TInterface::TTClockAdjustCheckBox
TCheckBox * TTClockAdjustCheckBox
Definition: InterfaceUnit.h:229
TOnePrefDir::SavePrefDirVector
void SavePrefDirVector(int Caller, std::ofstream &VecFile)
Save the preferred direction vector to a file.
Definition: TrackUnit.cpp:11472
TInterface::TrackNotLinkedImage
TImage * TrackNotLinkedImage
Definition: InterfaceUnit.h:275
TTrain::DepartureTimeSet
bool DepartureTimeSet
set when stopped at a location and the next action is departure (set in UpdateTrain when ReleaseTime ...
Definition: TrainUnit.h:347
TInterface::WarningHover
bool WarningHover
true when mouse hovers over warning messages during operation - to prevent clicking while changing
Definition: InterfaceUnit.h:1003
TTrack::GetTrackLocsFromScreenPos
void GetTrackLocsFromScreenPos(int Caller, int &HLoc, int &VLoc, int ScreenPosH, int ScreenPosV)
Converse of GetScreenPositionsFromTruePos except that in this function HLoc & VLoc are expressed in t...
Definition: TrackUnit.cpp:6859
TInterface::SaveTTAsButton
TButton * SaveTTAsButton
Definition: InterfaceUnit.h:146
TInterface::ZoomButtonClick
void __fastcall ZoomButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8608
TInterface::SpeedButton90
TSpeedButton * SpeedButton90
Definition: InterfaceUnit.h:594
TTrain::LagElement
int LagElement
Definition: TrainUnit.h:327
TTrack::GetLocationName
AnsiString GetLocationName(unsigned int InactiveTrackVectorPosition)
Return location name for a given inactive track vector position.
Definition: TrackUnit.h:717
TTrainController::BufferAttentionWarning
bool BufferAttentionWarning
Definition: TrainUnit.h:724
TInterface::ExitTrackButtonClick
void __fastcall ExitTrackButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1704
TTrainController::TrainVectorAtIdent
TTrain & TrainVectorAtIdent(int Caller, int TrainID)
Return a reference to the train with ID TrainID, carries out validity checking on TrainID.
Definition: TrainUnit.cpp:8624
TInterface::SpeedButton135
TSpeedButton * SpeedButton135
Definition: InterfaceUnit.h:639
TInterface::SpeedButton111
TSpeedButton * SpeedButton111
Definition: InterfaceUnit.h:615
TInterface::RouteCancelFlag
bool RouteCancelFlag
true when route cancel button pressed, enables a right mouse click to cancel a route if in an appropr...
Definition: InterfaceUnit.h:965
TTextHandler::LoadText
void LoadText(int Caller, std::ifstream &VecFile)
load the railway's text from VecFile
Definition: TextUnit.cpp:281
TInterface::SpeedToggleButton2Click
void __fastcall SpeedToggleButton2Click(TObject *Sender)
Definition: InterfaceUnit.cpp:11268
TOnePrefDir::GetStartAndEndPrefDirElements
bool GetStartAndEndPrefDirElements(int Caller, TPrefDirElement &StartElement, TPrefDirElement &EndElement, int &LastIteratorValue)
Called when searching for start and end PrefDirElements when setting up automatic signals routes in P...
Definition: TrackUnit.cpp:12565
TTextItem::HPos
int HPos
the horizontal position on the railway
Definition: TextUnit.h:48
TTrainController::StopTTClockMessage
void StopTTClockMessage(int Caller, AnsiString Message)
sends a message to the user and stops the timetable clock while it is displayed
Definition: TrainUnit.cpp:14000
TInterface::LoadNormalSignalGlyphs
void LoadNormalSignalGlyphs(int Caller)
In trackbuild display normal signal types on signal buttons.
Definition: InterfaceUnit.cpp:18472
TInterface::MainScreenMouseDown3
void MainScreenMouseDown3(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
Called when mouse button clicked in zoom-out mode.
Definition: InterfaceUnit.cpp:7051
TInterface::TTLabel11
TLabel * TTLabel11
Definition: InterfaceUnit.h:348
TInterface::CancelTTEntryButton
TButton * CancelTTEntryButton
Definition: InterfaceUnit.h:137
TInterface::SpeedButton8
TSpeedButton * SpeedButton8
Definition: InterfaceUnit.h:512
TInterface::UserGraphicVectorNumber
int UserGraphicVectorNumber
used to store a single item of user graphics
Definition: InterfaceUnit.h:1100
TInterface::PreviousTTEntryButton
TButton * PreviousTTEntryButton
Definition: InterfaceUnit.h:128
TInterface::TrackElementPanel
TPanel * TrackElementPanel
panel containing the track/location/parapet element buttons
Definition: InterfaceUnit.h:376
TAllRoutes::RemoveRouteElement
void RemoveRouteElement(int Caller, int HLoc, int VLoc, int ELink)
Erases the route element from Route2MultiMap and from the PrefDirVector.
Definition: TrackUnit.cpp:16901
TInterface::SelectionValid
bool SelectionValid
true when an area of screen has been selected via the 'Edit' & 'Select' or 'Reselect' menu items
Definition: InterfaceUnit.h:971
TDisplay::InvertElement
void InvertElement(int Caller, int HPos, int VPos)
Definition: DisplayUnit.cpp:140
TInterface::OperateButtonClick
void __fastcall OperateButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2031
TInterface::WhiteBgndMenuItem
TMenuItem * WhiteBgndMenuItem
Definition: InterfaceUnit.h:425
TTrack::IsReadyForOperation
bool IsReadyForOperation()
Indicates whether or not the railway is ready for saving as a '.rly' file and for operation.
Definition: TrackUnit.h:723
TInterface::ContinuationAutoSignals
void ContinuationAutoSignals(int Caller, TDateTime Now)
Deal with signal resetting on auto signal routes that extend to continuations where trains have depar...
Definition: InterfaceUnit.cpp:14259
TTrainController::CrashWarning
bool CrashWarning
Definition: TrainUnit.h:724
TInterface::LoadInterface
void LoadInterface(int Caller, std::ifstream &SessionFile)
Load the interface part of a session file.
Definition: InterfaceUnit.cpp:16257
TInterface::SpeedButton2
TSpeedButton * SpeedButton2
Definition: InterfaceUnit.h:506
TTrain::PlotTrain
void PlotTrain(int Caller, TDisplay *Disp)
Plots the train on the display in normal (zoomed-in) mode.
Definition: TrainUnit.cpp:7612
TInterface::AutoSigsFlag
bool AutoSigsFlag
true when AutoSig route building selected during operation
Definition: InterfaceUnit.h:927
TInterface::SetRouteButtonsInfoCaptionAndRouteNotStarted
void SetRouteButtonsInfoCaptionAndRouteNotStarted(int Caller)
Enables or disables the route type buttons depending on the route mode, sets the information panel me...
Definition: InterfaceUnit.cpp:17627
TInterface::MoveForwardsMenuItem
TMenuItem * MoveForwardsMenuItem
Definition: InterfaceUnit.h:463
TInterface::YardEdit
TEdit * YardEdit
Definition: InterfaceUnit.h:100
TTrack::CheckActiveLCVector
bool CheckActiveLCVector(int Caller, std::ifstream &VecFile)
Definition: TrackUnit.cpp:3264
TTrack::FindSetAndDisplayMatchingGap
bool FindSetAndDisplayMatchingGap(int Caller, int HLoc, int VLoc)
True if find an unset gap that matches the gap at HLoc & VLoc, if find one mark it with a green circl...
Definition: TrackUnit.cpp:4005
TInterface::Paused
@ Paused
Definition: InterfaceUnit.h:873
TTrainController::SaveSessionTrains
void SaveSessionTrains(int Caller, std::ofstream &SessionFile)
save trains to a session file
Definition: TrainUnit.cpp:14015
TInterface::SpeedButton41
TSpeedButton * SpeedButton41
Definition: InterfaceUnit.h:545
TInterface::TrackInfoMenuItem
TMenuItem * TrackInfoMenuItem
Definition: InterfaceUnit.h:444
TRailGraphics::SpeedBut73NormBlackGlyph
Graphics::TBitmap * SpeedBut73NormBlackGlyph
Definition: GraphicUnit.h:1049
TInterface::Operating
@ Operating
Definition: InterfaceUnit.h:873
TTextHandler
A single object that handles text management.
Definition: TextUnit.h:62
TInterface::EditTimetableMenuItemClick
void __fastcall EditTimetableMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3161
TInterface::TakeSignallerControlMenuItemClick
void __fastcall TakeSignallerControlMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9733
TInterface::TimetableMode
@ TimetableMode
Definition: InterfaceUnit.h:851
TInterface::ScreenUpButtonClick
void __fastcall ScreenUpButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8549
TInterface::ShowHideTTButtonClick
void __fastcall ShowHideTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3338
TInterface::ImageMenu
TMenuItem * ImageMenu
Definition: InterfaceUnit.h:450
TInterface::LoadGroundSignalGlyphs
void LoadGroundSignalGlyphs(int Caller)
In trackbuild display ground signal types on signal buttons.
Definition: InterfaceUnit.cpp:18488
TUtilities::LoadFileDouble
double LoadFileDouble(std::ifstream &InFile)
loads a double value from the file (converts from a string to a double) and uses the local decimal po...
Definition: Utilities.cpp:164
TInterface::CPArrivalsCheckBox
TCheckBox * CPArrivalsCheckBox
Definition: InterfaceUnit.h:242
TInterface::OneEntryTimetableMemo
TMemo * OneEntryTimetableMemo
the single service editing and display area on the right hand side of the timetable edit screen
Definition: InterfaceUnit.h:397
TInterface::SelectBitmapVLoc
int SelectBitmapVLoc
the original (prior to moving & after finished moving) VLoc value of Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1078
TInterface::LengthOKButtonClick
void __fastcall LengthOKButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1359
TInterface::SpeedButton47
TSpeedButton * SpeedButton47
Definition: InterfaceUnit.h:551
TInterface::OutputLog1MouseDown
void __fastcall OutputLog1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11027
NotStarted
@ NotStarted
Definition: TrainUnit.h:80
TTrack::ShowSelectedGap
void ShowSelectedGap(int Caller, TDisplay *Disp)
Called during gap setting to mark a gap with a red circle - after which the program awaits user selec...
Definition: TrackUnit.cpp:4164
TInterface::AppDeactivate
void __fastcall AppDeactivate(TObject *Sender)
Definition: InterfaceUnit.cpp:758
TInterface::UnrestrictedButtonClick
void __fastcall UnrestrictedButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2124
TInterface::ExportTTMenuItem
TMenuItem * ExportTTMenuItem
Definition: InterfaceUnit.h:415
TInterface::SaveTTKeyFlag
bool SaveTTKeyFlag
Definition: InterfaceUnit.h:1024
TRailGraphics::SpeedBut71NormBlackGlyph
Graphics::TBitmap * SpeedBut71NormBlackGlyph
Definition: GraphicUnit.h:1047
TInterface::SelectNewGraphicClick
void __fastcall SelectNewGraphicClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12287
TInterface::SpeedButtonClick
void __fastcall SpeedButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:883
TTrack::GetHLocMax
int GetHLocMax()
Definition: TrackUnit.h:767
TTrack::CheckUserGraphics
bool CheckUserGraphics(int Caller, std::ifstream &InFile, UnicodeString GraphicsPath)
checks all user graphics & returns true for success
Definition: TrackUnit.cpp:3140
TInterface::CPEditArrRange
TEdit * CPEditArrRange
Definition: InterfaceUnit.h:245
TInterface::ErrorButtonClick
void __fastcall ErrorButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10427
TTrainController::SPADEvents
int SPADEvents
Definition: TrainUnit.h:771
TInterface::PasteTTEntryButton
TButton * PasteTTEntryButton
Definition: InterfaceUnit.h:132
TInterface::SpeedButton139
TSpeedButton * SpeedButton139
Definition: InterfaceUnit.h:643
TInterface::SpeedButton3
TSpeedButton * SpeedButton3
Definition: InterfaceUnit.h:507
TTrain::ZeroPowerNoRepeatShuttleMessage
bool ZeroPowerNoRepeatShuttleMessage
Definition: TrainUnit.h:307
TTrackElement::SigAspect
enum TTrackElement::@1 SigAspect
TInterface::SetLevel2PrefDirMode
void SetLevel2PrefDirMode(int Caller)
Sets the Level2PrefDirMode user mode, using the Level2PrefDirMode variable to determine the mode.
Definition: InterfaceUnit.cpp:13988
TInterface::SetGapsButton
TBitBtn * SetGapsButton
Definition: InterfaceUnit.h:64
TTrain::ActionVectorEntryPtr
TActionVectorEntry * ActionVectorEntryPtr
points to the current position in the ActionVector (a member of the TTrainDataEntry class)
Definition: TrainUnit.h:335
TTrainDataEntry
Contains all data for a single train.
Definition: TrainUnit.h:177
clSignalStopBackground
#define clSignalStopBackground
Definition: GraphicUnit.h:299
TTrainController::LateDeps
int LateDeps
Definition: TrainUnit.h:764
TAllRoutes::IsElementInLockedRouteGetPrefDirElementGetLockedVectorNumber
bool IsElementInLockedRouteGetPrefDirElementGetLockedVectorNumber(int Caller, int TrackVectorPosition, int XLinkPos, TPrefDirElement &PrefDirElement, int &LockedVectorNumber)
Checks whether the preferred direction element at TrackVectorPosition with XLinkPos value is in a loc...
Definition: TrackUnit.cpp:17353
TInterface::ExitMenuItemClick
void __fastcall ExitMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5388
TrackUnit.h
TInterface::SpeedButton29
TSpeedButton * SpeedButton29
Definition: InterfaceUnit.h:533
TInterface::SpeedButton35
TSpeedButton * SpeedButton35
Definition: InterfaceUnit.h:539
TInterface::ScreenDownButtonClick
void __fastcall ScreenDownButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8489
TAllRoutes::CheckRoutes
bool CheckRoutes(int Caller, int NumberOfActiveElements, std::ifstream &InFile)
Performs an integrity check on the routes stored in a session file and returns false if there is an e...
Definition: TrackUnit.cpp:17544
TTrack::LengthMarker
void LengthMarker(int Caller, TDisplay *Disp)
Examine all elements in the TrackVector and if have a valid length mark the relevant track using Mark...
Definition: TrackUnit.cpp:8534
TDisplay::ClearDisplay
void ClearDisplay(int Caller)
Empty the display.
Definition: DisplayUnit.cpp:181
TDisplay::Top
int Top()
Return the top pixel position of the screen.
Definition: DisplayUnit.h:120
TInterface::ExitPrefDirButtonClick
void __fastcall ExitPrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1993
TInterface::SaveErrorFile
void SaveErrorFile()
Save the error log after an error has been thrown - no need for a caller.
Definition: InterfaceUnit.cpp:17729
TTrain::SendMissedActionLogs
void SendMissedActionLogs(int Caller, int IncNum, TActionVectorEntry *Ptr)
Missed actions (see NameInTimetableBeforeCDT above) sent to the performance log and performance file.
Definition: TrainUnit.cpp:5854
TInterface::SpeedVariableLabel2
TLabel * SpeedVariableLabel2
Definition: InterfaceUnit.h:113
TInterface::TrainInfoMenuItem
TMenuItem * TrainInfoMenuItem
Definition: InterfaceUnit.h:446
TOneRoute::RouteID
int RouteID
the ID number of the route, this is needed for session saves
Definition: TrackUnit.h:1405
TAllRoutes
Handles data and functions relating to all routes on the railway.
Definition: TrackUnit.h:1491
TInterface::TrainStatusInfoOnOffMenuItemClick
void __fastcall TrainStatusInfoOnOffMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5452
TInterface::ConverttoRightHandSignalsMenuItem
TMenuItem * ConverttoRightHandSignalsMenuItem
Definition: InterfaceUnit.h:468
TInterface::SpeedButton96
TSpeedButton * SpeedButton96
Definition: InterfaceUnit.h:600
TInterface::TTClockxHalfButtonClick
void __fastcall TTClockxHalfButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11762
TInterface::OutputLog3
TLabel * OutputLog3
Definition: InterfaceUnit.h:294
TUserGraphicItem::VPos
int VPos
Definition: DisplayUnit.h:34
TOnePrefDir::ExternalStorePrefDirElement
void ExternalStorePrefDirElement(int Caller, TPrefDirElement LoadPrefDirElement)
Store a single pref dir element in the vector & map - used by other classes.
Definition: TrackUnit.h:1320
clB5G5R4
#define clB5G5R4
Definition: GraphicUnit.h:285
Utilities.h
TTrainController::TContinuationAutoSigVectorIterator
TContinuationAutoSigVector::iterator TContinuationAutoSigVectorIterator
Definition: TrainUnit.h:660
TInterface::SaveImageNoGridMenuItemClick
void __fastcall SaveImageNoGridMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2508
TInterface::SpeedButton25
TSpeedButton * SpeedButton25
Definition: InterfaceUnit.h:529
TInterface::HelpMenu
TMenuItem * HelpMenu
Definition: InterfaceUnit.h:456
TInterface::TrackOKButtonClick
void __fastcall TrackOKButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:960
TTrainController::CheckSessionLockedRoutes
bool CheckSessionLockedRoutes(int Caller, std::ifstream &SessionFile)
Part of the session file integrity check for locked routes, true for success.
Definition: TrainUnit.cpp:14119
TTrack::SaveTrack
void SaveTrack(int Caller, std::ofstream &VecFile, bool GraphicsFollow)
Save all active and inactive track elements to VecFile.
Definition: TrackUnit.cpp:2868
TInterface::GapsSetImage
TImage * GapsSetImage
Definition: InterfaceUnit.h:276
TDisplay::Update
void Update()
Repaint the screen display.
Definition: DisplayUnit.h:221
TUserGraphicItem::HPos
int HPos
Definition: DisplayUnit.h:34
TInterface::LocationNameComboBoxKeyUp
void __fastcall LocationNameComboBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:4660
TTrainController::CreateTTAnalysisFile
bool CreateTTAnalysisFile(int Caller, AnsiString RailwayTitle, AnsiString TimetableTitle, AnsiString CurDir, bool ArrChecked, bool DepChecked, bool AtLocChecked, int ArrRange, int DepRange)
Generate a timetable analysis file in the 'Formatted Timetables' folder, return false if failed for a...
Definition: TrainUnit.cpp:14961
TInterface::RevertToOriginalRouteSelector
void RevertToOriginalRouteSelector(int Caller)
Clears any route start markers, enables or disables the route cancel button, and resets the informati...
Definition: InterfaceUnit.cpp:12895
TInterface::FileIntegrityCheck
bool FileIntegrityCheck(int Caller, char *FileName) const
Check integrity of a railway file prior to loading, return true for success.
Definition: InterfaceUnit.cpp:12742
TInterface::TTLastServicePtr
TTEVPtr TTLastServicePtr
timetable entry value pointers used during timetable editing
Definition: InterfaceUnit.h:1141
TTrainController::CheckSessionTrains
bool CheckSessionTrains(int Caller, std::ifstream &InFile)
Part of the session file integrity check for train entries, true for success.
Definition: TrainUnit.cpp:14057
TInterface::SpeedButton126
TSpeedButton * SpeedButton126
Definition: InterfaceUnit.h:630
TakeSignallerControl
@ TakeSignallerControl
Definition: TrainUnit.h:49
TOnePrefDir::EraseFromPrefDirVectorAnd4MultiMap
void EraseFromPrefDirVectorAnd4MultiMap(int Caller, int HLoc, int VLoc)
Erase element at HLoc and VLoc from the PrefDirVector and from the 4MultiMap. Note that this entails ...
Definition: TrackUnit.cpp:11538
Simple
@ Simple
Definition: TrackUnit.h:63
TTrack::GapFlashGreen
TGraphicElement * GapFlashGreen
Definition: TrackUnit.h:690
TTrain::ZeroPowerNoRepeatShuttleOrNewServiceMessage
bool ZeroPowerNoRepeatShuttleOrNewServiceMessage
flags to indicate whether the respective message has been sent
Definition: TrainUnit.h:308
TUtilities::RHSignalFlag
bool RHSignalFlag
new at v2.3.0 false=LH signals
Definition: Utilities.h:40
TInterface::SetInitialTrackModeEditMenu
void SetInitialTrackModeEditMenu()
Enables or disables the initial Edit mode submenu items in Track mode.
Definition: InterfaceUnit.cpp:18261
TInterface::DeleteMenuItem
TMenuItem * DeleteMenuItem
Definition: InterfaceUnit.h:438
TTrack::NumberOfGaps
int NumberOfGaps(int Caller)
Returns the number of gaps in the railway.
Definition: TrackUnit.cpp:2496
TInterface::TTClockAdjustOKButtonClick
void __fastcall TTClockAdjustOKButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12304
TInterface::ChangeDirectionMenuItemClick
void __fastcall ChangeDirectionMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9924
TInterface::PointsFlashDuration
float PointsFlashDuration
duration of the flash period when changing points manually
Definition: InterfaceUnit.h:1035
TInterface::LocationNameComboBoxClick
void __fastcall LocationNameComboBoxClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4589
TInterface::TTServiceSyntaxCheckKeyFlag
bool TTServiceSyntaxCheckKeyFlag
Definition: InterfaceUnit.h:1022
TInterface::TLevel2OperMode
TLevel2OperMode
Definition: InterfaceUnit.h:872
TInterface::ConsecSignalsRoute
bool ConsecSignalsRoute
true when AutoSig or preferred route building selected during operation (always same state as Preferr...
Definition: InterfaceUnit.h:929
TOnePrefDir::CheckPrefDirAgainstTrackVectorNoMessage
bool CheckPrefDirAgainstTrackVectorNoMessage(int Caller)
Check loaded PrefDir against loaded track, and if discrepancies found clear EveryPrefDir & PrefDir4Mu...
Definition: TrackUnit.cpp:11766
TTrack::GetVectorPositionsFromInactiveTrackMap
TIMPair GetVectorPositionsFromInactiveTrackMap(int Caller, int HLoc, int VLoc, bool &FoundFlag)
Similar to GetVectorPositionFromTrackMap but for inactive elements, a pair is returned because there ...
Definition: TrackUnit.cpp:5195
TTrain::BackgroundColour
TColor BackgroundColour
the background colour of the train's headcode graphics
Definition: TrainUnit.h:450
TInterface::LengthCancelButtonClick
void __fastcall LengthCancelButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1541
TTrain
Definition: TrainUnit.h:271
TInterface::OutputLog5
TLabel * OutputLog5
Definition: InterfaceUnit.h:296
TTrainController::CheckTimeValidity
bool CheckTimeValidity(int Caller, AnsiString TimeStr, TDateTime &Time)
returns true if the time complies with requirements
Definition: TrainUnit.cpp:9759
clSignallerStopped
#define clSignallerStopped
Definition: GraphicUnit.h:298
TTextHandler::SelectTextVector
TTextVector SelectTextVector
Definition: TextUnit.h:69
TTrackElement::TrainIDOnBridgeTrackPos23
int TrainIDOnBridgeTrackPos23
Set to the TrainID value when a train is present on the element, bridges can have two trains present ...
Definition: TrackUnit.h:151
TOnePrefDir::GetFixedPrefDirElementAt
const TPrefDirElement & GetFixedPrefDirElementAt(int Caller, int At) const
Return a non-modifiable element at PrefDirVector position 'At'.
Definition: TrackUnit.cpp:10234
TInterface::CallOnImage
TImage * CallOnImage
Definition: InterfaceUnit.h:262
TInterface::PerformancePanelDragStartY
int PerformancePanelDragStartY
as above for 'Y'
Definition: InterfaceUnit.h:1069
TInterface::LocationNameTextBox
TEdit * LocationNameTextBox
edit box that accepts location names
Definition: InterfaceUnit.h:94
TTrack::PlotLoweredLinkedLevelCrossingBarriers
void PlotLoweredLinkedLevelCrossingBarriers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, int ConsecSignals, TDisplay *Disp, bool Manual)
Plot & open (to trains) all level crossings linked to TrackElement (Manual true = manually lowered,...
Definition: TrackUnit.cpp:5765
TTrack::TActiveLevelCrossing::VLoc
int VLoc
VLoc value for found level crossing element.
Definition: TrackUnit.h:542
TInterface::SaveSessionFlag
bool SaveSessionFlag
true when a session save command has been given - implemented at next clock tick
Definition: InterfaceUnit.h:967
TTrainController::ContinuationTrainExpectationMultiMap
TContinuationTrainExpectationMultiMap ContinuationTrainExpectationMultiMap
Multimap for TContinuationTrainExpectationEntry objects, the access key is the expectation time.
Definition: TrainUnit.h:794
TTrack::GetTruePositionsFromScreenPos
void GetTruePositionsFromScreenPos(int Caller, int &HPos, int &VPos, int ScreenPosH, int ScreenPosV)
Converse of GetScreenPositionsFromTruePos.
Definition: TrackUnit.cpp:6874
TInterface::SpeedButton73
TSpeedButton * SpeedButton73
Definition: InterfaceUnit.h:577
TInterface::TTLabel4
TLabel * TTLabel4
Definition: InterfaceUnit.h:342
TTrain::StoppedForTrainInFront
bool StoppedForTrainInFront
Definition: TrainUnit.h:427
TInterface::ConflictAnalysisKeyFlag
bool ConflictAnalysisKeyFlag
Definition: InterfaceUnit.h:1028
GapJump
@ GapJump
Definition: TrackUnit.h:63
TInterface::Level2OperMode
enum TInterface::TLevel2OperMode Level2OperMode
TInterface::SigsOnRightImage1
TImage * SigsOnRightImage1
Definition: InterfaceUnit.h:282
TInterface::SaveRailwayPDPButton
TBitBtn * SaveRailwayPDPButton
Save button on PrefDirPanel.
Definition: InterfaceUnit.h:119
TInterface::SpeedButton62
TSpeedButton * SpeedButton62
Definition: InterfaceUnit.h:566
TInterface::SpeedButton58
TSpeedButton * SpeedButton58
Definition: InterfaceUnit.h:562
TTrainController::MissedStops
int MissedStops
Definition: TrainUnit.h:766
TInterface::TempTTFileName
AnsiString TempTTFileName
the name for the temporary file used to save loaded timetables for storage in session files & error l...
Definition: InterfaceUnit.h:918
TInterface::PrefDirMode
@ PrefDirMode
Definition: InterfaceUnit.h:851
TInterface::PassRedSignalMenuItem
TMenuItem * PassRedSignalMenuItem
Definition: InterfaceUnit.h:464
TTrackElement::Length01
int Length01
Definition: TrackUnit.h:147
TRailGraphics::bmGreenRect
Graphics::TBitmap * bmGreenRect
Definition: GraphicUnit.h:520
TInterface::TTClockExitButtonClick
void __fastcall TTClockExitButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11625
TTrackElement::SpeedLimit01
int SpeedLimit01
Definition: TrackUnit.h:147
TTrack::Raising
@ Raising
Definition: TrackUnit.h:523
TTrainController::FinishedOperation
void FinishedOperation(int Caller)
called when exiting operation mode to delete all trains and timetable data etc
Definition: TrainUnit.cpp:8225
TTextHandler::FindText
bool FindText(int Caller, AnsiString Name, int &HPos, int &VPos)
look in TextVector for text item 'Name', and if found return true and return its position in &HPos an...
Definition: TextUnit.cpp:557
TTrack::UserGraphicMove
void UserGraphicMove(int Caller, int HPosInput, int VPosInput, int &UserGraphicItem, int &UserGraphicMoveHPos, int &UserGraphicMoveVPos, bool &UserGraphicFoundFlag)
handles moving of user graphics
Definition: TrackUnit.cpp:9261
TDisplay::DisplayOffsetV
static int DisplayOffsetV
the vertical offset of the displayed screen
Definition: DisplayUnit.h:78
TTrain::MidElement
int MidElement
Definition: TrainUnit.h:327
TOneRoute::SetRouteFlashValues
void SetRouteFlashValues(int Caller, bool AutoSigsFlag, bool ConsecSignalsRoute)
After a route has been selected successfully this function sets all RouteFlash (see above) values app...
Definition: TrackUnit.cpp:15900
TInterface::SpeedButton5
TSpeedButton * SpeedButton5
Definition: InterfaceUnit.h:509
TInterface::LocationNameKeyUp
void __fastcall LocationNameKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:1152
TInterface::LoadUserGraphicDialog
TOpenDialog * LoadUserGraphicDialog
Definition: InterfaceUnit.h:491
TAllRoutes::CallonVector
std::vector< TCallonEntry > CallonVector
the store of all call-on entries
Definition: TrackUnit.h:1550
TInterface::OutputLog8MouseDown
void __fastcall OutputLog8MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11095
TInterface::SetPausedOrZoomedInfoCaption
void SetPausedOrZoomedInfoCaption(int Caller)
Sets the information panel message for zoom-out or paused modes.
Definition: InterfaceUnit.cpp:17698
TTrain::LeadElement
int LeadElement
Definition: TrainUnit.h:327
TInterface::CurDir
AnsiString CurDir
the full path to the folder where railway.exe resides
Definition: InterfaceUnit.h:904
TInterface::OneEntryTimetableMemoKeyUp
void __fastcall OneEntryTimetableMemoKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:4617
TInterface::RouteCancelButton
TBitBtn * RouteCancelButton
Definition: InterfaceUnit.h:198
TInterface::SpeedButton26
TSpeedButton * SpeedButton26
Definition: InterfaceUnit.h:530
TInterface::HomeButton
TBitBtn * HomeButton
Definition: InterfaceUnit.h:253
TRailGraphics
Handles graphic data & functions, single object defined.
Definition: GraphicUnit.h:308
TInterface::OperatorActionPanelDragStartY
int OperatorActionPanelDragStartY
as above for 'Y'
Definition: InterfaceUnit.h:1062
TTrain::RepeatNumber
int RepeatNumber
indicates which of the repeating services this train represents (0 = first service)
Definition: TrainUnit.h:321
TTrainDataEntry::ActionVector
TActionVector ActionVector
all the actions for the train
Definition: TrainUnit.h:195
TTrainController::BaseTime
TDateTime BaseTime
CurrentDateTime (i.e. real time) when operation restarts after a pause.
Definition: TrainUnit.h:633
TInterface::NewHomeButton
TBitBtn * NewHomeButton
Definition: InterfaceUnit.h:254
TInterface::ResetAll
void ResetAll(int Caller)
Called during ClearEverything and on startup to reset all major railway data values.
Definition: InterfaceUnit.cpp:15635
TInterface::SpeedButton75
TSpeedButton * SpeedButton75
Definition: InterfaceUnit.h:579
TTrainController::LoadSessionLockedRoutes
void LoadSessionLockedRoutes(int Caller, std::ifstream &SessionFile)
load locked routes from a session file
Definition: TrainUnit.cpp:14098
TInterface::DistancesMarked
bool DistancesMarked
true when setting lengths, used to ensure the screen distance markers are redisplayed when the screen...
Definition: InterfaceUnit.h:937
TTrainController::EarlyPasses
int EarlyPasses
Definition: TrainUnit.h:761
TTrain::HeadCode
AnsiString HeadCode
needs own HeadCode because repeat entries will differ from TrainDataEntry.HeadCode
Definition: TrainUnit.h:290
TInterface::TrackBuildPanel
TPanel * TrackBuildPanel
'Build/modify railway' panel
Definition: InterfaceUnit.h:357
TTrain::EntryTime
TDateTime EntryTime
Definition: TrainUnit.h:409
TInterface::CutMoving
@ CutMoving
Definition: InterfaceUnit.h:882
TInterface::SpeedButton134
TSpeedButton * SpeedButton134
Definition: InterfaceUnit.h:638
TInterface::SelectLengthsMenuItem
TMenuItem * SelectLengthsMenuItem
Definition: InterfaceUnit.h:439
TOnePrefDir::PrefDirSize
unsigned int PrefDirSize() const
Return the vector size.
Definition: TrackUnit.h:1271
TInterface::SpeedButton72
TSpeedButton * SpeedButton72
Definition: InterfaceUnit.h:576
TInterface::ValidateTimetableButton
TButton * ValidateTimetableButton
Definition: InterfaceUnit.h:144
TTrack::PlotSignal
void PlotSignal(int Caller, TTrackElement TrackElement, TDisplay *Disp)
Plot signals on screen according to their aspect (Attribute value)
Definition: TrackUnit.cpp:5426
TUserGraphicItem
Definition: DisplayUnit.h:31
TOneRoute::RouteFlash
TRouteFlash RouteFlash
the class member that allows the route to flash during setting up (see TRouteFlash above)
Definition: TrackUnit.h:1411
InterfaceUnit.h
TInterface::CopyMenuItemClick
void __fastcall CopyMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8928
TInterface::PerformanceLogButton
TBitBtn * PerformanceLogButton
Definition: InterfaceUnit.h:200
TInterface::FORMATTEDTT_DIR_NAME
static const UnicodeString FORMATTEDTT_DIR_NAME
Definition: InterfaceUnit.h:867
TInterface::HighLightOneGap
bool HighLightOneGap(int Caller, int &HLoc, int &VLoc)
Called during gap setting to mark a gap with a red ellipse and ask user to select the corresponding g...
Definition: InterfaceUnit.cpp:12664
TTrain::OneLengthAccelDecel
bool OneLengthAccelDecel
set when a train can only move forwards one element before stopping but needs to accelerate for the f...
Definition: TrainUnit.h:357
TTrain::FloatingLabelNextString
AnsiString FloatingLabelNextString(int Caller, TActionVectorEntry *Ptr)
Used in the floating window to display the 'Next' action.
Definition: TrainUnit.cpp:6414
TTrack::TActiveLevelCrossing::BarrierState
TBarrierState BarrierState
state of barriers
Definition: TrackUnit.h:534
TTrain::FailedTrainNoFinishJoinMessage
bool FailedTrainNoFinishJoinMessage
Definition: TrainUnit.h:302
TInterface::SpeedButton55
TSpeedButton * SpeedButton55
Definition: InterfaceUnit.h:559
TInterface::OperatorActionPanel
TPanel * OperatorActionPanel
new v2.2.0 panel housing the OAListBox with list of trains and times to act
Definition: InterfaceUnit.h:385
TInterface::NextTTEntryButton
TButton * NextTTEntryButton
Definition: InterfaceUnit.h:129
TTextHandler::SelectTextVectorSize
unsigned int SelectTextVectorSize(int Caller)
return the number of items in SelectTextVector
Definition: TextUnit.cpp:516
TInterface::TrackTrainFloat
void TrackTrainFloat(int Caller)
Controls the floating window function, called during the ClockTimer2 function.
Definition: InterfaceUnit.cpp:14316
TDisplay::GetImage
TImage * GetImage()
Return a pointer to the screen image.
Definition: DisplayUnit.h:138
clB0G0R5
#define clB0G0R5
Definition: GraphicUnit.h:41
TInterface::AddLocationNameText
void AddLocationNameText(int Caller, AnsiString Name, int HPos, int VPos, bool UseEnteredPosition)
Add 'Name' to TextVector and display on screen at a position determined by the shape and size of the ...
Definition: InterfaceUnit.cpp:18367
TTrack::InactiveTrackElementAt
TTrackElement & InactiveTrackElementAt(int Caller, int At)
A range-checked version of InactiveTrackElement.at(At)
Definition: TrackUnit.cpp:9367
TTextHandler::CheckTextElementsInFile
bool CheckTextElementsInFile(int Caller, std::ifstream &VecFile)
check the validity of text items in VecFile prior to loading, return true for success
Definition: TextUnit.cpp:349
TInterface::ConverttoRightHandSignalsMenuItemClick
void __fastcall ConverttoRightHandSignalsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12072
TPrefDirElement::GetTrackVectorPosition
unsigned int GetTrackVectorPosition() const
Returns TrackVectorPosition.
Definition: TrackUnit.h:295
TTrack::GetVLocMax
int GetVLocMax()
Definition: TrackUnit.h:777
TTrainController::LoadSessionContinuationAutoSigEntries
void LoadSessionContinuationAutoSigEntries(int Caller, std::ifstream &SessionFile)
load ContinuationAutoSigEntries from a session file
Definition: TrainUnit.cpp:14181
TInterface::HighlightOneEntryInAllEntriesTTListBox
void HighlightOneEntryInAllEntriesTTListBox(int Caller, int Position)
Called during timetable editing to highlight in red a single entry in the list of all entries in the ...
Definition: InterfaceUnit.cpp:5322
TInterface::DistanceStart
@ DistanceStart
Definition: InterfaceUnit.h:881
TInterface::ErrorMessage
TMemo * ErrorMessage
the text of the normal error message screen
Definition: InterfaceUnit.h:393
TInterface::ExitPrefDirButton
TBitBtn * ExitPrefDirButton
Definition: InterfaceUnit.h:121
TTrack::LNPendingList
TLNPendingList LNPendingList
list of location name elements awaiting processing (see type for more information above)
Definition: TrackUnit.h:698
TTrackElement
Basic track elements as implemented in the overall railway layout.
Definition: TrackUnit.h:123
TInterface::TrackLengthPanel
TPanel * TrackLengthPanel
the panel that contains the distance/speed setting buttons and edit boxes
Definition: InterfaceUnit.h:378
TUtilities::Format96HHMMSS
AnsiString Format96HHMMSS(TDateTime DateTime)
formats a TDateTime into an AnsiString of the form hh:mm:ss where hh runs from 00 to 95 & resets when...
Definition: Utilities.cpp:520
TTrack::RebuildUserGraphics
void RebuildUserGraphics(int Caller, TDisplay *Disp)
rebuild user graphics
Definition: TrackUnit.cpp:3423
TRailGraphics::bmSolidBgnd
Graphics::TBitmap * bmSolidBgnd
Definition: GraphicUnit.h:988
TRailGraphics::smSolidBgnd
Graphics::TBitmap * smSolidBgnd
Definition: GraphicUnit.h:989
TTrack::GroundSignalBuild
@ GroundSignalBuild
Definition: TrackUnit.h:754
TTrainController::OtherMissedEvents
int OtherMissedEvents
Definition: TrainUnit.h:770
TTextHandler::WriteTextToImage
void WriteTextToImage(int Caller, Graphics::TBitmap *Bitmap)
write all items in TextVector to the railway image in 'Bitmap'
Definition: TextUnit.cpp:425
TInterface::MoveTextOrGraphicButton
TBitBtn * MoveTextOrGraphicButton
Definition: InterfaceUnit.h:67
TTrainDataEntry::Description
AnsiString Description
headcode is the first train's headcode, rest are calculated from repeat information; ServiceReference...
Definition: TrainUnit.h:179
TInterface::RouteContinuing
@ RouteContinuing
Definition: InterfaceUnit.h:886
TTrain::ExitSpeedHalf
double ExitSpeedHalf
speed when half way into the next element
Definition: TrainUnit.h:377
SignalPost
@ SignalPost
Definition: TrackUnit.h:63
TTrack::SetAllDefaultLengthsAndSpeedLimits
void SetAllDefaultLengthsAndSpeedLimits(int Caller)
Work through all elements in TrackVector setting all lengths & speed limits to default values - inclu...
Definition: TrackUnit.cpp:8499
TTrain::LastActionTime
TDateTime LastActionTime
time of the last timetabled action, used to ensure at least a 30 second delay before the next action
Definition: TrainUnit.h:413
TAllRoutes::WriteAllRoutesToImage
void WriteAllRoutesToImage(int Caller, Graphics::TBitmap *Bitmap)
Calls RouteImageMarker for each route in turn to display the route colours and direction arrows on th...
Definition: TrackUnit.cpp:16054
IDInt::GetInt
int GetInt() const
get the internal integer
Definition: TrackUnit.h:421
TInterface::InfoPanel
TPanel * InfoPanel
the general information panel (with blue 'i' symbol)
Definition: InterfaceUnit.h:372
TInterface::TextOrUserGraphicGridButtonClick
void __fastcall TextOrUserGraphicGridButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1759
TInterface::FormKeyDown
void __fastcall FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:10530
TTrack::TActiveLevelCrossing::ConsecSignals
int ConsecSignals
route type - 0 = nonsignals, 1 = preferred direction (can't have autosigs), 2 no route,...
Definition: TrackUnit.h:530
TInterface::MoveTTEntryDownButton
TButton * MoveTTEntryDownButton
Definition: InterfaceUnit.h:135
TInterface::CheckTimetableFromSessionFile
bool CheckTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
Check the timetable file embedded within a session file & return false for error, called during Sessi...
Definition: InterfaceUnit.cpp:16811
TRailGraphics::SpeedBut71GrndBlackGlyph
Graphics::TBitmap * SpeedBut71GrndBlackGlyph
Definition: GraphicUnit.h:1055
TInterface::DeleteTTEntryButtonClick
void __fastcall DeleteTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3793
TTrack::GetScreenPositionsFromTruePos
void GetScreenPositionsFromTruePos(int Caller, int &ScreenPosH, int &ScreenPosV, int HPosTrue, int VPosTrue)
With large railways only part of the railway is displayed on screen, and this function converts true ...
Definition: TrackUnit.cpp:6888
TTrack::PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers
void PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, TDisplay *Disp, bool Manual)
Plot LC elements without any base elements, and set LCPlotted true - used in ClearandRebuildRailway (...
Definition: TrackUnit.cpp:6170
TInterface::WarningFlashCount
int WarningFlashCount
increments each clock cycle to a max. of 4 then resets to 0, used to toggle bool WarningFlash - see a...
Definition: InterfaceUnit.h:1104
TInterface::StartWholeRailwayMoveHPos
int StartWholeRailwayMoveHPos
mouse X position when start to move the whole railway
Definition: InterfaceUnit.h:1082
TInterface::SpeedButton93
TSpeedButton * SpeedButton93
Definition: InterfaceUnit.h:597
TInterface::SpeedButton119
TSpeedButton * SpeedButton119
Definition: InterfaceUnit.h:623
TInterface::SelectedGraphicFileName
AnsiString SelectedGraphicFileName
filename for selected graphic set during LoadGraphic
Definition: InterfaceUnit.h:922
TTrack::EraseLocationAndActiveTrackElementNames
void EraseLocationAndActiveTrackElementNames(int Caller, AnsiString LocationName)
Examines LocationNameMultiMap and if the LocationName is found all elements at that H & V (in both ac...
Definition: TrackUnit.cpp:7839
TInterface::TrackBuildPanelLabel
TLabel * TrackBuildPanelLabel
label to the left of TrackBuildPanel
Definition: InterfaceUnit.h:315
clNormalBackground
#define clNormalBackground
Definition: GraphicUnit.h:297
TInterface::TTClockAdjButtonClick
void __fastcall TTClockAdjButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11594
TInterface::RAILWAY_DIR_NAME
static const UnicodeString RAILWAY_DIR_NAME
Definition: InterfaceUnit.h:862
TTrainController::SecondPassActions
bool SecondPassActions(int Caller, bool GiveMessages)
Carry out further detailed timetable consistency checks, return true for success.
Definition: TrainUnit.cpp:10797
TAllRoutes::MarkAllRoutes
void MarkAllRoutes(int Caller, TDisplay *Disp)
Calls PrefDirMarker for all routes, with RouteCall set to identify a route call, and BuildingPrefDir ...
Definition: TrackUnit.cpp:16039
TInterface::SPADImage
TImage * SPADImage
Definition: InterfaceUnit.h:266
TInterface::AddTrackButton
TBitBtn * AddTrackButton
Definition: InterfaceUnit.h:63
TInterface::MainMenu1
TMainMenu * MainMenu1
the program menu
Definition: InterfaceUnit.h:390
TInterface::OutputLog7MouseDown
void __fastcall OutputLog7MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11085
Concourse
@ Concourse
Definition: TrackUnit.h:64
TTextHandler::TTextVectorIterator
std::vector< TTextItem >::iterator TTextVectorIterator
Definition: TextUnit.h:66
TTrainController::SPADRisks
int SPADRisks
Definition: TrainUnit.h:772
TInterface::LocationNamesNotSetImage
TImage * LocationNamesNotSetImage
Definition: InterfaceUnit.h:279
TInterface::FloatingPanel
TPanel * FloatingPanel
new for v2.2.0 where label sits in it and it autosizes to the label. Labels are not TWinControls so t...
Definition: InterfaceUnit.h:382
TRailGraphics::SpeedBut68NormBlackGlyph
Graphics::TBitmap * SpeedBut68NormBlackGlyph
Definition: GraphicUnit.h:1044
TTrack::SelectVector
TTrackVector SelectVector
vectors of TrackElements
Definition: TrackUnit.h:707
TInterface::SaveMenuItemClick
void __fastcall SaveMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2440
TInterface::ScreenGridButtonClick
void __fastcall ScreenGridButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1863
TTrain::EntrySpeed
double EntrySpeed
speed at which the train enters the next element
Definition: TrainUnit.h:375
TInterface::UserGraphicMoveHPos
int UserGraphicMoveHPos
Definition: InterfaceUnit.h:1102
TInterface::PassRedSignalMenuItemClick
void __fastcall PassRedSignalMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10196
TInterface::ReselectMenuItem
TMenuItem * ReselectMenuItem
Definition: InterfaceUnit.h:431
TOnePrefDir::WritePrefDirToImage
void WritePrefDirToImage(int Caller, Graphics::TBitmap *Bitmap)
Used when creating a bitmap image to display preferred directions (as on screen during 'Set preferred...
Definition: TrackUnit.cpp:12222
TInterface::ClearEverything
bool ClearEverything(int Caller)
First check whether a railway file has changed and if so ask user if really wants to close it without...
Definition: InterfaceUnit.cpp:12692
TInterface::PrefDirContinuing
@ PrefDirContinuing
Definition: InterfaceUnit.h:877
TTrain::TrainGone
bool TrainGone
set when train has left the railway, so it can be removed from the display at the next clock tick
Definition: TrainUnit.h:423
TRailGraphics::SpeedBut70NormBlackGlyph
Graphics::TBitmap * SpeedBut70NormBlackGlyph
Definition: GraphicUnit.h:1046
TTrainController::OnTimePasses
int OnTimePasses
Definition: TrainUnit.h:769
TInterface::SaveAsMenuItem
TMenuItem * SaveAsMenuItem
Definition: InterfaceUnit.h:411
TInterface::MoveTextOrGraphicButtonClick
void __fastcall MoveTextOrGraphicButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1074
TTrainController::SigSHigh
bool SigSHigh
Definition: TrainUnit.h:738
TTrack::NoGaps
bool NoGaps(int Caller)
True if there are no gaps.
Definition: TrackUnit.cpp:4089
TInterface::ZoomButton
TBitBtn * ZoomButton
Definition: InterfaceUnit.h:255
TGraphicElement::PlotOriginal
void PlotOriginal(int Caller, TDisplay *Disp)
Plot the original graphic on screen.
Definition: TrackUnit.cpp:1597
TextHandler
TTextHandler * TextHandler
Definition: TextUnit.cpp:94
TInterface::CopyTTEntryButton
TButton * CopyTTEntryButton
Definition: InterfaceUnit.h:130
TInterface::ErrorMessageStoreImage
TMemo * ErrorMessageStoreImage
the text of the error message for failure to draw trains in SaveOperatingImage
Definition: InterfaceUnit.h:395
TInterface::SpeedButton76
TSpeedButton * SpeedButton76
Definition: InterfaceUnit.h:580
TTrain::StoppedAfterSPAD
bool StoppedAfterSPAD
Definition: TrainUnit.h:427
TInterface::SpeedButton145
TSpeedButton * SpeedButton145
Definition: InterfaceUnit.h:649
TInterface::NoPrefDirMode
@ NoPrefDirMode
Definition: InterfaceUnit.h:877
TInterface::SpeedButton88
TSpeedButton * SpeedButton88
Definition: InterfaceUnit.h:592
TTrainController::OnTimeArrivals
int OnTimeArrivals
Definition: TrainUnit.h:767
TInterface::MoveTTEntryDownButtonClick
void __fastcall MoveTTEntryDownButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4303
TInterface::PerformanceLogBox
TMemo * PerformanceLogBox
the performance log displayed during operation
Definition: InterfaceUnit.h:399
TRailGraphics::SpeedBut72GrndBlackGlyph
Graphics::TBitmap * SpeedBut72GrndBlackGlyph
Definition: GraphicUnit.h:1056
TInterface::SpeedButton28
TSpeedButton * SpeedButton28
Definition: InterfaceUnit.h:532
TAllRoutes::LevelCrossingBarrierUpDelay
const float LevelCrossingBarrierUpDelay
the full value in seconds for which the level crossing flashes prior to closing to trains
Definition: TrackUnit.h:1570
TInterface::SpeedTopLabel
TLabel * SpeedTopLabel
Definition: InterfaceUnit.h:180
TInterface::OperateButton
TBitBtn * OperateButton
Definition: InterfaceUnit.h:194
clFrontCodeSignaller
#define clFrontCodeSignaller
Definition: GraphicUnit.h:295
TInterface::SignallerJoinedByMenuItemClick
void __fastcall SignallerJoinedByMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10017
TTrack::MirrorArray
int MirrorArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'mirroring' via menu items 'Edit' & 'Mirror'
Definition: TrackUnit.h:672
TUserGraphicItem::Width
int Width
Definition: DisplayUnit.h:35
Utilities
TUtilities * Utilities
Definition: Utilities.cpp:47
TActionVectorEntry::ArrivalTime
TDateTime ArrivalTime
Definition: TrainUnit.h:106
TTrain::StoppedAtBuffers
bool StoppedAtBuffers
Definition: TrainUnit.h:427
TInterface::SkipFormResizeEvent
bool SkipFormResizeEvent
added at v2.1.0 to avoid calling the event during startup and shutdown
Definition: InterfaceUnit.h:981
TTrain::Mass
int Mass
in kg
Definition: TrainUnit.h:405
TInterface::TrackInfoOnOffMenuItem
TMenuItem * TrackInfoOnOffMenuItem
Definition: InterfaceUnit.h:445
TDisplay::ShowWarningLog
void ShowWarningLog(int Caller)
Show the warnings after timetable clock adjusted.
Definition: DisplayUnit.cpp:493
TInterface::SpeedButton121
TSpeedButton * SpeedButton121
Definition: InterfaceUnit.h:625
TTrainController::ProcessOneTimetableLine
bool ProcessOneTimetableLine(int Caller, int Count, AnsiString OneLine, bool &EndOfFile, bool FinalCall, bool GiveMessages, bool CheckLocationsExistInRailway)
Carry out preliminary (mainly syntax) validity checks on a single timetable service entry and (if Fin...
Definition: TrainUnit.cpp:9109
TInterface::SaveAsMenuItemClick
void __fastcall SaveAsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2491
TTextItem
A single piece of text that can be displayed on the railway.
Definition: TextUnit.h:36
TInterface::SpeedButton136
TSpeedButton * SpeedButton136
Definition: InterfaceUnit.h:640
TInterface::PointFlash
TGraphicElement * PointFlash
Definition: InterfaceUnit.h:1118
TInterface::TrackLinkedImage
TImage * TrackLinkedImage
Definition: InterfaceUnit.h:274
TTrain::LeadExitPos
int LeadExitPos
Definition: TrainUnit.h:327
TInterface::SelectPickedUp
bool SelectPickedUp
true when a valid selected screen area has been clicked after a 'Copy' or 'Cut' selected in the 'Edit...
Definition: InterfaceUnit.h:975
TDisplay::ResetZoomOutOffsets
void ResetZoomOutOffsets()
Reset the zoomed-out screen display to the 'Home' position.
Definition: DisplayUnit.h:208
TTrackElement::ThreeAspect
@ ThreeAspect
Definition: TrackUnit.h:156
TInterface::DevelopmentPanel
TPanel * DevelopmentPanel
used for diagnostic purposes, made visible by ctrl+ alt+ 3
Definition: InterfaceUnit.h:380
TTrack::NoActiveOrInactiveTrack
bool NoActiveOrInactiveTrack(int Caller)
True if there is no active or inactive track in the railway.
Definition: TrackUnit.cpp:1616
TInterface::PerformancePanel
TPanel * PerformancePanel
displays the operating performance log
Definition: InterfaceUnit.h:374
TTrainController::DerailWarning
bool DerailWarning
Definition: TrainUnit.h:724
TInterface::CopyMoving
@ CopyMoving
Definition: InterfaceUnit.h:882
TInterface::TimetableEditPanel
TPanel * TimetableEditPanel
the large panel that contains all the main timetable components
Definition: InterfaceUnit.h:366
TInterface::RouteMode
enum TInterface::@0 RouteMode
route building modes
TDisplay::DisplayZoomOutOffsetVHome
static int DisplayZoomOutOffsetVHome
the vertical offset of the zoomed-out 'Home' display
Definition: DisplayUnit.h:90
TInterface::TrainStatusInfoOnOffMenuItem
TMenuItem * TrainStatusInfoOnOffMenuItem
Definition: InterfaceUnit.h:447
TInterface::SetLengthsButtonClick
void __fastcall SetLengthsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1338
TInterface::SaveTTEntryButton
TButton * SaveTTEntryButton
Definition: InterfaceUnit.h:136
TInterface::SpeedButton37
TSpeedButton * SpeedButton37
Definition: InterfaceUnit.h:541
TInterface::BaseMode
@ BaseMode
Definition: InterfaceUnit.h:851
TInterface::SpeedEditBoxKeyUp
void __fastcall SpeedEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11289
TTrack::DiagonalFouledByTrain
bool DiagonalFouledByTrain(int Caller, int HLoc, int VLoc, int DiagonalLinkNumber, int &TrainID)
Definition: TrackUnit.cpp:10047
TInterface::MirrorMenuItem
TMenuItem * MirrorMenuItem
Definition: InterfaceUnit.h:435
TInterface::EveryPrefDir
TOnePrefDir * EveryPrefDir
all the Pref Dir elements in the railway
Definition: InterfaceUnit.h:1129
TTrainController::TotLateDepMins
float TotLateDepMins
Definition: TrainUnit.h:754
TDisplay::ZoomOutFlag
bool ZoomOutFlag
true when zoomed-out
Definition: DisplayUnit.h:69
TInterface::OutputLog8
TLabel * OutputLog8
Definition: InterfaceUnit.h:299
TInterface::SpeedButton1
TSpeedButton * SpeedButton1
See Speedbutton1 detail for track element allocations.
Definition: InterfaceUnit.h:505
TTrainController::TrainVector
TTrainVector TrainVector
vector containing all trains currently in the railway
Definition: TrainUnit.h:802
TInterface::SaveAsSubroutine
void SaveAsSubroutine(int Caller)
Used to save a railway when not already saved - e.g. when not already named or when the 'Save as' men...
Definition: InterfaceUnit.cpp:18161
TInterface::MainScreenMouseDown2
void MainScreenMouseDown2(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
Called when mouse button clicked in zoom-in mode.
Definition: InterfaceUnit.cpp:5629
TOneRoute::ClearRoute
void ClearRoute()
Empty the route of any stored elements.
Definition: TrackUnit.h:1417
TInterface::RepairFailedTrainMenuItemClick
void __fastcall RepairFailedTrainMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10106
TInterface::AddLocationName
@ AddLocationName
Definition: InterfaceUnit.h:881
TTrack::LocationNameAllocated
bool LocationNameAllocated(int Caller, AnsiString LocationName)
True if a non-empty LocationName found in LocationNameMultiMap.
Definition: TrackUnit.cpp:7787
TTrack::IsTrackFinished
bool IsTrackFinished()
Indicates whether or not the track has been successfully linked together.
Definition: TrackUnit.h:729
TAllRoutes::AllRoutesClear
void AllRoutesClear()
Erases all routes from AllRoutesVector and from Route2MultiMap.
Definition: TrackUnit.h:1598
TRailGraphics::SpeedBut74GrndBlackGlyph
Graphics::TBitmap * SpeedBut74GrndBlackGlyph
Definition: GraphicUnit.h:1058
TAllRoutes::PointsDelay
const float PointsDelay
the value in seconds for which points flash prior to being changed. Used for the points flash period ...
Definition: TrackUnit.h:1574
TInterface::SaveSession
void SaveSession(int Caller)
Save a session file - see LoadSession for details of additions to the session file.
Definition: InterfaceUnit.cpp:15843
TUtilities::CallLogPop
void CallLogPop(int Caller)
pops the last entry off the call stack, throws an error if called when empty
Definition: Utilities.cpp:50
TAllRoutes::SignalsDelay
const float SignalsDelay
the value in seconds for which signals flash prior to being changed. Used for the route flash period ...
Definition: TrackUnit.h:1576
TDisplay::GetFont
TFont * GetFont()
Return the current screen font.
Definition: DisplayUnit.h:132
TInterface::SpeedButton10
TSpeedButton * SpeedButton10
Definition: InterfaceUnit.h:514
TTrain::MaximumSpeedLimit
static const int MaximumSpeedLimit
km/h
Definition: TrainUnit.h:284
TInterface::SpeedButton103
TSpeedButton * SpeedButton103
Definition: InterfaceUnit.h:607
TTrack::ThreeAspectBuild
@ ThreeAspectBuild
Definition: TrackUnit.h:754
TTrainController::TotEarlyArrMins
float TotEarlyArrMins
values for performance file summary
Definition: TrainUnit.h:750
TInterface::PerformancePanelStartDrag
void __fastcall PerformancePanelStartDrag(TObject *Sender, TDragObject *&DragObject)
Definition: InterfaceUnit.cpp:5557
TInterface::TempCursorSet
bool TempCursorSet
indicates that a screen cursor has been stored in TempCursor for redisplay after a temporary cursor (...
Definition: InterfaceUnit.h:983
TOnePrefDir::GetPrefDirTruncateElement
bool GetPrefDirTruncateElement(int Caller, int HLoc, int VLoc)
Called during PrefDir build or distance setting. It truncates at & including the first element in the...
Definition: TrackUnit.cpp:11025
TInterface::SpeedButton85
TSpeedButton * SpeedButton85
Definition: InterfaceUnit.h:589
TInterface::PasteMenuItemClick
void __fastcall PasteMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9514
TInterface::MainScreenMouseUp
void __fastcall MainScreenMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:7355
TDisplay::PlotOutput
void PlotOutput(int Caller, int HPos, int VPos, Graphics::TBitmap *PlotItem)
Plot the graphic at screen position HPos & VPos.
Definition: DisplayUnit.cpp:85
TInterface::SaveTempTimetableFile
void SaveTempTimetableFile(int Caller, AnsiString InFileName)
Save a timetable as a temporary file either on loading directly or on loading a session file....
Definition: InterfaceUnit.cpp:17922
TAllRoutes::AllRoutesVector
TAllRoutesVector AllRoutesVector
the vector that stores all the routes on the railway
Definition: TrackUnit.h:1580
TUtilities::SaveFileBool
void SaveFileBool(std::ofstream &OutFile, bool SaveBool)
stores '1' if the bool is true or '0' if false to the file, then a CR
Definition: Utilities.cpp:108
TInterface::RotateMenuItemClick
void __fastcall RotateMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9063
TTrainDataEntry::SignallerSpeed
int SignallerSpeed
in km/h for use when under signaller control
Definition: TrainUnit.h:191
TInterface::OverallDistance
int OverallDistance
Definition: InterfaceUnit.h:1064
TInterface::SpeedButton105
TSpeedButton * SpeedButton105
Definition: InterfaceUnit.h:609
TInterface::SpeedButton83
TSpeedButton * SpeedButton83
Definition: InterfaceUnit.h:587
TTrain::AbleToMove
bool AbleToMove(int Caller)
Indicates that a train is not prevented from moving - used to allow appropriate popup menu options wh...
Definition: TrainUnit.cpp:6279
TTrainController::MTBFHours
double MTBFHours
Mean time between failures in timetable clock hours.
Definition: TrainUnit.h:741
TOnePrefDir::SaveSearchVector
void SaveSearchVector(int Caller, std::ofstream &VecFile)
Save the search vector to a file.
Definition: TrackUnit.cpp:11505
TInterface::RestoreAllDefaultLengthsButtonClick
void __fastcall RestoreAllDefaultLengthsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1669
TInterface::LengthWarningSentFlag
bool LengthWarningSentFlag
indicates that the length selection applying to all elements in the selection warning has been given,...
Definition: InterfaceUnit.h:947
TInterface::SpeedButton131
TSpeedButton * SpeedButton131
Definition: InterfaceUnit.h:635
TOneRoute::GetNextPreferredRouteElement
bool GetNextPreferredRouteElement(int Caller, int HLoc, int VLoc, TOnePrefDir *EveryPrefDir, bool ConsecSignalsRoute, bool AutoSigsFlag, IDInt &ReqPosRouteID, bool &PointsChanged)
Try to find a set of linked tracks that lie on preferred directions between the route start element a...
Definition: TrackUnit.cpp:13044
TInterface::FlipMenuItemClick
void __fastcall FlipMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8947
TInterface::TrainTTInfoOnOffMenuItem
TMenuItem * TrainTTInfoOnOffMenuItem
Definition: InterfaceUnit.h:448
TInterface::AllSetUpFlag
bool AllSetUpFlag
false during initial start up, true when all set up to allow MasterClock to start
Definition: InterfaceUnit.h:925
TTrack::SaveChangingLCVector
void SaveChangingLCVector(int Caller, std::ofstream &OutFile)
Save all changing vector values (used for error file)
Definition: TrackUnit.cpp:3241
TInterface::LocationNameButton
TBitBtn * LocationNameButton
Definition: InterfaceUnit.h:68
TInterface::SpeedButton101
TSpeedButton * SpeedButton101
Definition: InterfaceUnit.h:605
TTrain::TrainMode
TTrainMode TrainMode
mode of operation - either Timetable (running under timetable control) or Signaller (running under si...
Definition: TrainUnit.h:415
TInterface::LoadRailway
void LoadRailway(int Caller, AnsiString LoadFileName)
Load a railway file. The Active elements marker now has a '1' at the end if there are user graphics t...
Definition: InterfaceUnit.cpp:2311
TTrack::SaveUserGraphics
void SaveUserGraphics(int Caller, std::ofstream &VecFile)
save graphics
Definition: TrackUnit.cpp:10094
TInterface::TextOrUserGraphicGridButton
TBitBtn * TextOrUserGraphicGridButton
Definition: InterfaceUnit.h:70
TInterface::PointFlashVectorPosition
int PointFlashVectorPosition
Definition: InterfaceUnit.h:1071
TInterface::AddSubMinsBoxKeyUp
void __fastcall AddSubMinsBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:4642
TInterface::ExitOperationButtonClick
void __fastcall ExitOperationButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2213
TGraphicElement::LoadOriginalScreenGraphic
void LoadOriginalScreenGraphic(int Caller)
Load original graphic from the screen for point flashing or route start markers.
Definition: TrackUnit.cpp:1499
TInterface::TTClockAdd1hButtonClick
void __fastcall TTClockAdd1hButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11837
TUtilities::Format96HHMM
AnsiString Format96HHMM(TDateTime DateTime)
formats a TDateTime into an AnsiString of the form hh:mm where hh runs from 00 to 95 & resets when it...
Definition: Utilities.cpp:535
TInterface::TTClockx2ButtonClick
void __fastcall TTClockx2ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11667
TInterface::PerformancePanelDragStartX
int PerformancePanelDragStartX
mouse 'X' position when the performance panel begins to be dragged
Definition: InterfaceUnit.h:1067
TInterface::SpeedButton45
TSpeedButton * SpeedButton45
Definition: InterfaceUnit.h:549
TInterface::SpeedEditBox2KeyUp
void __fastcall SpeedEditBox2KeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11443
TInterface::SavedFileName
AnsiString SavedFileName
the full path and filename of the loaded railway
Definition: InterfaceUnit.h:916
TInterface::FillSelectionMessageSentFlag
bool FillSelectionMessageSentFlag
indicates that the message about filling a selected area with a chosen track element has been given,...
Definition: InterfaceUnit.h:943
TInterface::PlanPrefDirsMenuItemClick
void __fastcall PlanPrefDirsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1890
TInterface::OperatingPanel
TPanel * OperatingPanel
'Operate railway' panel
Definition: InterfaceUnit.h:363
TTrack::SelectVectorSize
unsigned int SelectVectorSize()
Return the number of selected active and inactive track elements (via menu items 'Edit' and 'Select')
Definition: TrackUnit.h:815
TInterface::SpeedButton141
TSpeedButton * SpeedButton141
Definition: InterfaceUnit.h:645
TInterface::ShowOperatorActionPanel
bool ShowOperatorActionPanel
true when the 'trains needing action' button has been clicked during operation (new at v2....
Definition: InterfaceUnit.h:997
TTrack::GetGapVLoc
int GetGapVLoc()
Definition: TrackUnit.h:762
TInterface::SpeedButton124
TSpeedButton * SpeedButton124
Definition: InterfaceUnit.h:628
TUtilities::CheckFileString
bool CheckFileString(std::ifstream &InFile)
checks that the value is a string ('0' or CR accepted as delimiters), returns true for success
Definition: Utilities.cpp:356
TOnePrefDir::LoadPrefDir
void LoadPrefDir(int Caller, std::ifstream &VecFile)
Load a vector and map of preferred directions from the file.
Definition: TrackUnit.cpp:11325
TRailGraphics::bmGrid
Graphics::TBitmap * bmGrid
Definition: GraphicUnit.h:521
TInterface::RestoreFocusPanel
TPanel * RestoreFocusPanel
Panel used to restore focus to Interface to enable cursor keys to move screen.
Definition: InterfaceUnit.h:354
TInterface::BlackBgndMenuItem
TMenuItem * BlackBgndMenuItem
Definition: InterfaceUnit.h:426
SignallerControlStop
@ SignallerControlStop
Definition: TrainUnit.h:51
TTrack::TrackVector
TTrackVector TrackVector
Definition: TrackUnit.h:707
TTrack::TActiveLevelCrossing::BaseElementSpeedTag
int BaseElementSpeedTag
SpeedTag value for the base element of a level crossing.
Definition: TrackUnit.h:538
TInterface::FloatingLabel
TLabel * FloatingLabel
the floating window that displays track & train information
Definition: InterfaceUnit.h:335
TInterface::NewTTEntryButton
TButton * NewTTEntryButton
Definition: InterfaceUnit.h:138
TTrainController::ExcessLCDownMins
float ExcessLCDownMins
total excess time in minutes over the 3 minutes barriers down allowance for level crossings
Definition: TrainUnit.h:748
TInterface::SubMinsButtonClick
void __fastcall SubMinsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3545
TGraphicElement
Allows a single Width x Height graphic to change and change back independently of the remaining displ...
Definition: TrackUnit.h:346
TInterface::TimetableControlMenuItemClick
void __fastcall TimetableControlMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9806
TTrack::TActiveTrackElementNameIterator
TActiveTrackElementNameMap::iterator TActiveTrackElementNameIterator
Definition: TrackUnit.h:616
TInterface::DistanceBox
TEdit * DistanceBox
distance/speed setting edit box that accepts distances
Definition: InterfaceUnit.h:90
TInterface::SpeedButton142
TSpeedButton * SpeedButton142
Definition: InterfaceUnit.h:646
TInterface::PresetAutoSigRoutesButton
TBitBtn * PresetAutoSigRoutesButton
Definition: InterfaceUnit.h:199
TTrackElement::CallingOnSet
bool CallingOnSet
Used for for signals only when a train is being called on - used to plot the position lights.
Definition: TrackUnit.h:133
TUtilities::SaveFileInt
void SaveFileInt(std::ofstream &OutFile, int SaveInt)
stores the int value to the file, then a CR
Definition: Utilities.cpp:117
TInterface::TTLabel12
TLabel * TTLabel12
Definition: InterfaceUnit.h:349
TInterface::TTServiceSyntaxCheckButtonClick
void __fastcall TTServiceSyntaxCheckButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4154
TInterface::SpeedButton57
TSpeedButton * SpeedButton57
Definition: InterfaceUnit.h:561
TInterface::TTClockSpeed
float TTClockSpeed
rate at which the timetable clock runs 1 = normal
Definition: InterfaceUnit.h:1039
TrainController
TTrainController * TrainController
the object pointer, one object only - created in InterfaceUnit
Definition: TrainUnit.cpp:54
TDisplay::PlotAbsolute
void PlotAbsolute(int Caller, int HPos, int VPos, Graphics::TBitmap *PlotItem)
Definition: DisplayUnit.cpp:419
TTrack::TrackElementPresentAtHV
bool TrackElementPresentAtHV(int Caller, int HLoc, int VLoc)
New at v1.2.0; true if a track element present (not inactive elements - see InactiveTrackElementPrese...
Definition: TrackUnit.cpp:5154
TGraphicElement::LoadOriginalExistingGraphic
void LoadOriginalExistingGraphic(int Caller, int HOffset, int VOffset, int WidthIn, int HeightIn, Graphics::TBitmap *Graphic)
Load red or green gap flashing graphic from the stored bitmaps.
Definition: TrackUnit.cpp:1533
TInterface::TTClockx4ButtonClick
void __fastcall TTClockx4ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11686
TOnePrefDir::CalcDistanceAndSpeed
void CalcDistanceAndSpeed(int Caller, int &OverallDistance, int &OverallSpeedLimit, bool &LeadingPointsAtLastElement)
Used when setting element lengths, returns in &OverallDistance the overall distance for the selected ...
Definition: TrackUnit.cpp:12159
TTextHandler::TextFound
bool TextFound(int Caller, int HPosInput, int VPosInput, AnsiString &Text)
look for a text item in the vicinity of HPosInput & VPosInput, return true if found & return the foun...
Definition: TextUnit.cpp:225
TInterface::LCManualLowerBarriersMessageSent
bool LCManualLowerBarriersMessageSent
indicates that the manual LC operation message has been given, so it won't be given again
Definition: InterfaceUnit.h:945
TInterface::SaveImageAndPrefDirsMenuItemClick
void __fastcall SaveImageAndPrefDirsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2697
TInterface::AddMinsButton
TButton * AddMinsButton
Definition: InterfaceUnit.h:141
SignallerStepForward
@ SignallerStepForward
Definition: TrainUnit.h:51
TTrack::GetHLocMin
int GetHLocMin()
Definition: TrackUnit.h:772
TTextHandler::TextPtrAt
TTextItem * TextPtrAt(int Caller, int At)
return the text item at position 'At' in TextVector (carries out range checking)
Definition: TextUnit.cpp:527
TInterface::SpeedButton60
TSpeedButton * SpeedButton60
Definition: InterfaceUnit.h:564
TInterface::TrackInfoOnOffMenuItemClick
void __fastcall TrackInfoOnOffMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5429
TTrack::WriteTrackToImage
void WriteTrackToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by TInterface::SaveImageNoGrid1Click, TInterface::SaveImageAndGrid1Click and TInterface::SaveI...
Definition: TrackUnit.cpp:3449
TTrainController::OpTimeToActUpdateCounter
unsigned int OpTimeToActUpdateCounter
new v2.2.0, incremented in Interface.cpp, controls updating for OpTimeToActPanel
Definition: TrainUnit.h:786
TTrain::BeingCalledOn
bool BeingCalledOn
in course of being called on to a station
Definition: TrainUnit.h:341
TUtilities::CheckFileInt
bool CheckFileInt(std::ifstream &InFile, int Lowest, int Highest)
checks that the value is an int lying between Lowest & Highest (inclusive), returns true for success
Definition: Utilities.cpp:217
TInterface::AZOrderButtonClick
void __fastcall AZOrderButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4964
TInterface::HiddenScreen
TImage * HiddenScreen
a hidden copy of the railway display screen used during ClearandRebuildRailway (see below) to avoid f...
Definition: InterfaceUnit.h:1124
TInterface::PerformancePanelLabelStartDrag
void __fastcall PerformancePanelLabelStartDrag(TObject *Sender, TDragObject *&DragObject)
Definition: InterfaceUnit.cpp:10438
TInterface::LoadPerformanceFile
void LoadPerformanceFile(int Caller, std::ifstream &InFile)
Load the performance file part of a sessionfile.
Definition: InterfaceUnit.cpp:17552
TInterface::CPCancelButtonClick
void __fastcall CPCancelButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12342
TInterface::OutputLog4MouseDown
void __fastcall OutputLog4MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11056
TInterface::AddGraphic
@ AddGraphic
Definition: InterfaceUnit.h:881
TInterface::SetLevel1Mode
void SetLevel1Mode(int Caller)
Sets the Level1 user mode, using the Level1Mode variable to determine the mode.
Definition: InterfaceUnit.cpp:12924
TInterface::NewHomeButtonClick
void __fastcall NewHomeButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8777
TInterface::OutputLog4
TLabel * OutputLog4
Definition: InterfaceUnit.h:295
TInterface::FontDialog
TFontDialog * FontDialog
font change dialog
Definition: InterfaceUnit.h:496
TInterface::TrackSelecting
@ TrackSelecting
Definition: InterfaceUnit.h:882
TTrainController::TotLateArrMins
float TotLateArrMins
Definition: TrainUnit.h:753
TInterface::Level2PrefDirMode
enum TInterface::TLevel2PrefDirMode Level2PrefDirMode
TInterface::OperatingPanelLabel
TLabel * OperatingPanelLabel
displays 'Operation' or 'Disabled' on the operating panel during operation for running or paused
Definition: InterfaceUnit.h:323
TInterface::DivergingPointVectorPosition
int DivergingPointVectorPosition
Definition: InterfaceUnit.h:1071
TInterface::OAListBoxMouseUp
void __fastcall OAListBoxMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:4737
TTrainController::PlotAllTrainsInZoomOutMode
void PlotAllTrainsInZoomOutMode(int Caller, bool Flash)
Plots all trains on screen in zoomed-out mode, state of 'Flash' determines whether the flashing train...
Definition: TrainUnit.cpp:14334
TInterface::SpeedButton108
TSpeedButton * SpeedButton108
Definition: InterfaceUnit.h:612
TOneRoute
A descendent of TOnePrefDir used for routes. Used during contruction of a route (ConstructRoute) and ...
Definition: TrackUnit.h:1367
TTrack::NamedLocationElementAt
bool NamedLocationElementAt(int Caller, int HLoc, int VLoc)
True if the active or inactive TrackElement at HLoc & VLoc has its FixedNamedLocationElement member t...
Definition: TrackUnit.cpp:7754
TInterface::SavePerformanceFile
void SavePerformanceFile(int Caller, std::ofstream &OutFile)
Save performance file part of a session file.
Definition: InterfaceUnit.cpp:17607
TTextItem::Font
TFont * Font
the text font
Definition: TextUnit.h:52
TAllRoutes::TLockedRouteVectorIterator
std::vector< TLockedRouteClass >::iterator TLockedRouteVectorIterator
Definition: TrackUnit.h:1521
TTrain::SignallerStopped
bool SignallerStopped
Definition: TrainUnit.h:427
TDisplay::SetFont
void SetFont(TFont *Font)
Set the screen font to 'Font'.
Definition: DisplayUnit.h:215
TAllRoutes::TRouteType
TRouteType
Definition: TrackUnit.h:1511
TTrain::TrainDataEntryPtr
TTrainDataEntry * TrainDataEntryPtr
points to the current position in the timetable's TrainDataVector
Definition: TrainUnit.h:333
TInterface::TTLabel13
TLabel * TTLabel13
Definition: InterfaceUnit.h:350
TTrainDataEntry::StartSpeed
int StartSpeed
in km/h
Definition: TrainUnit.h:193
TTrainDataEntry::NumberOfTrains
int NumberOfTrains
number of repeats + 1
Definition: TrainUnit.h:189
TTrainController::Derailments
int Derailments
Definition: TrainUnit.h:759
clStationStopBackground
#define clStationStopBackground
Definition: GraphicUnit.h:301
TInterface::AZOrderButton
TButton * AZOrderButton
Definition: InterfaceUnit.h:140
TInterface::SpeedButton86
TSpeedButton * SpeedButton86
Definition: InterfaceUnit.h:590
TInterface::SpeedButton122
TSpeedButton * SpeedButton122
Definition: InterfaceUnit.h:626
Crossover
@ Crossover
Definition: TrackUnit.h:63
TTrack::SetLinkedManualLCs
void SetLinkedManualLCs(int Caller, int HLoc, int VLoc)
Set all ConsecSignals values to 2 for all linked LCs to indicate manually lowered.
Definition: TrackUnit.cpp:5633
TInterface::SpeedButton104
TSpeedButton * SpeedButton104
Definition: InterfaceUnit.h:608
TInterface::SignallerJoinedByMenuItem
TMenuItem * SignallerJoinedByMenuItem
Definition: InterfaceUnit.h:477
TRailGraphics::SpeedBut69NormBlackGlyph
Graphics::TBitmap * SpeedBut69NormBlackGlyph
Definition: GraphicUnit.h:1045
TTrack::IsLCBarrierFlashingAtHV
bool IsLCBarrierFlashingAtHV(int Caller, int HLoc, int VLoc)
True if barrier is in process of opening or closing at H & V.
Definition: TrackUnit.cpp:6622
TDisplay::ResetZoomInOffsets
void ResetZoomInOffsets()
Reset the zoomed-in screen display to the 'Home' position.
Definition: DisplayUnit.h:201
TTrack::IsPlatformOrNamedNonStationLocationPresent
bool IsPlatformOrNamedNonStationLocationPresent(int Caller, int HLoc, int VLoc)
True if a non-station named location or platform at HLoc & VLoc.
Definition: TrackUnit.cpp:8853
TInterface::RotRightMenuItem
TMenuItem * RotRightMenuItem
Definition: InterfaceUnit.h:475
AtLocation
@ AtLocation
Definition: TrainUnit.h:67
TInterface::ExportTTButton
TButton * ExportTTButton
Definition: InterfaceUnit.h:148
DefaultTrackLength
#define DefaultTrackLength
Definition: TrackUnit.h:37
Signal
@ Signal
Definition: TrackUnit.h:73
TInterface::TimetableChangedFlag
bool TimetableChangedFlag
true when a timetable in the editor has changed (used to warn user if opts to exit without saving)
Definition: InterfaceUnit.h:991
TInterface::SaveTimetableToErrorFile
bool SaveTimetableToErrorFile(int Caller, std::ofstream &ErrorFile, AnsiString ErrorFileStr, AnsiString TimetableFileName)
Called when compiling the error log file, to save the loaded timetable if any and the timetable being...
Definition: InterfaceUnit.cpp:16615
TTrack::ContinuationNameMap
std::map< AnsiString, char > ContinuationNameMap
map of all continuation names, char is a dummy
Definition: TrackUnit.h:679
TAllRoutes::GetRouteTypeAndNumber
TRouteType GetRouteTypeAndNumber(int Caller, int TrackVectorPosition, int LinkPos, int &RouteNumber)
Examines Route2MultiMap and if the element at TrackVectorPosition with LinkPos (can be entry or exit)...
Definition: TrackUnit.cpp:16342
TTrackElement::TrainIDOnBridgeTrackPos01
int TrainIDOnBridgeTrackPos01
Definition: TrackUnit.h:151
TInterface::TrainHeadCodeMenuItem
TMenuItem * TrainHeadCodeMenuItem
Definition: InterfaceUnit.h:459
TTrainController::TrainDataVector
TTrainDataVector TrainDataVector
vector containing the internal timetable
Definition: TrainUnit.h:800
TOnePrefDir::CheckOnePrefDir
bool CheckOnePrefDir(int Caller, int NumberOfActiveElements, std::ifstream &VecFile)
Called before PrefDir loading as part of the FileIntegrityCheck function in case there is an error in...
Definition: TrackUnit.cpp:11375
TTrain::ExitTimeHalf
TDateTime ExitTimeHalf
Definition: TrainUnit.h:409
Exited
@ Exited
Definition: TrainUnit.h:80
TInterface::OutputLog2
TLabel * OutputLog2
Definition: InterfaceUnit.h:293
TInterface::TTClockAdjustWarningLabel
TLabel * TTClockAdjustWarningLabel
Definition: InterfaceUnit.h:230
TInterface::SpeedButton74
TSpeedButton * SpeedButton74
Definition: InterfaceUnit.h:578
TInterface::ScreenRightButtonClick
void __fastcall ScreenRightButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8430
TInterface::PositionalPanel
TPanel * PositionalPanel
Definition: InterfaceUnit.h:384
TInterface::StepForwardMenuItemClick
void __fastcall StepForwardMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10239
TInterface::ErrorLog
void ErrorLog(int Caller, AnsiString Message)
The error logging routine, called when an error is detected.
Definition: InterfaceUnit.cpp:15506
TInterface::SpeedButton50
TSpeedButton * SpeedButton50
Definition: InterfaceUnit.h:554
TTrack::TrackElementAt
TTrackElement & TrackElementAt(int Caller, int At)
A range-checked version of TrackElement.at(At)
Definition: TrackUnit.cpp:9354
TTrainController::LoadSessionTrains
void LoadSessionTrains(int Caller, std::ifstream &SessionFile)
load trains from a session file
Definition: TrainUnit.cpp:14031
TInterface::SpeedButton31
TSpeedButton * SpeedButton31
Definition: InterfaceUnit.h:535
TInterface::UserGraphicFoundFlag
bool UserGraphicFoundFlag
indicates that a user graphic item has been found when clicking on a build screen for moving
Definition: InterfaceUnit.h:989
TInterface::RouteCancelButtonClick
void __fastcall RouteCancelButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2164
TInterface::SpeedButton91
TSpeedButton * SpeedButton91
Definition: InterfaceUnit.h:595
TInterface::SelectedTrainID
int SelectedTrainID
used to store the train ID when right clicked for signaller control actions
Definition: InterfaceUnit.h:1080
TInterface::SpeedButton113
TSpeedButton * SpeedButton113
Definition: InterfaceUnit.h:617
TInterface::SpeedButton82
TSpeedButton * SpeedButton82
Definition: InterfaceUnit.h:586
TTextHandler::SelectTextPtrAt
TTextItem * SelectTextPtrAt(int Caller, int At)
return the text item at position 'At' in SelectTextVector (carries out range checking)
Definition: TextUnit.cpp:542
TInterface::SpeedButton132
TSpeedButton * SpeedButton132
Definition: InterfaceUnit.h:636
TTrack::ChangingLCVector
TActiveLCVector ChangingLCVector
vector of values for changing level crossings - i.e. barriers in course of being raised or lowered
Definition: TrackUnit.h:684
TInterface::FlashingGraphics
void FlashingGraphics(int Caller, TDateTime Now)
Deal with any warning graphics that need to flash (call on, signal stop, crash etc),...
Definition: InterfaceUnit.cpp:14948
TInterface::ScreenLeftButton
TBitBtn * ScreenLeftButton
Definition: InterfaceUnit.h:250
TTrain::StoppedAtLocation
bool StoppedAtLocation
Definition: TrainUnit.h:427
TTrainController::TContinuationTrainExpectationMultiMapIterator
TContinuationTrainExpectationMultiMap::iterator TContinuationTrainExpectationMultiMapIterator
iterator for the multimap
Definition: TrainUnit.h:684
TInterface::TTClockx16ButtonClick
void __fastcall TTClockx16ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11724
TInterface::BuildTrackMenuItem
TMenuItem * BuildTrackMenuItem
Definition: InterfaceUnit.h:420
TInterface::SaveOperatingImageMenuItem
TMenuItem * SaveOperatingImageMenuItem
Definition: InterfaceUnit.h:454
TTrainController::StopTTClockFlag
bool StopTTClockFlag
when true the timetable clock is stopped, used for messages display and train popup menu display etc
Definition: TrainUnit.h:726
TInterface::NoRailway
bool NoRailway()
Returns true if there are no track elements and no text.
Definition: InterfaceUnit.cpp:18331
TInterface::AllEntriesTTListBox
TListBox * AllEntriesTTListBox
the list of service entries displayed on the left hand side of the timetable edit screen
Definition: InterfaceUnit.h:404
TInterface::CallingOnButtonClick
void __fastcall CallingOnButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8340
TInterface::SaveTTDialog
TSaveDialog * SaveTTDialog
Definition: InterfaceUnit.h:495
TInterface::DeleteOnePrefDirButtonClick
void __fastcall DeleteOnePrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1965
TTrack::WriteOperatingTrackToImage
void WriteOperatingTrackToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by TInterface::SaveOperatingImage1Click to add all track element graphics to the image file in...
Definition: TrackUnit.cpp:3733
TAllRoutes::NextRouteID
int NextRouteID
stores the value for the route ID number that is next to be built
Definition: TrackUnit.h:1578
TUtilities::CheckAndReadFileString
bool CheckAndReadFileString(std::ifstream &InFile, AnsiString &OutString)
checks that the value is a string ('0' or CR accepted as delimiters), returns true for success and re...
Definition: Utilities.cpp:468
TInterface::TTEntryChangedFlag
bool TTEntryChangedFlag
true when a timetable entry that is displayed in the timetable entry edit window has changed
Definition: InterfaceUnit.h:999
TInterface::HighlightPanel
TPanel * HighlightPanel
the orange bar that displays the current timetable entry in AllEntriesTTListBox
Definition: InterfaceUnit.h:370
TInterface::SpeedButton16
TSpeedButton * SpeedButton16
Definition: InterfaceUnit.h:520
TInterface::MoveTTEntryUpButtonClick
void __fastcall MoveTTEntryUpButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4241
TInterface::SpeedBottomLabel
TLabel * SpeedBottomLabel
Definition: InterfaceUnit.h:181
TTrainController::BFHigh
bool BFHigh
Definition: TrainUnit.h:738
TUserGraphicItem::FileName
AnsiString FileName
Definition: DisplayUnit.h:33
TInterface::TTClockResetButtonClick
void __fastcall TTClockResetButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11897
TInterface::ClockLabel
TLabel * ClockLabel
the timetable clock
Definition: InterfaceUnit.h:321
TInterface::SpeedButton43
TSpeedButton * SpeedButton43
Definition: InterfaceUnit.h:547
TTrain::LagEntryPos
int LagEntryPos
Definition: TrainUnit.h:327
TInterface::SetTrackBuildImages
void SetTrackBuildImages(int Caller)
Sets the left screen images (track linked or not, gaps set or not, locations named or not) during rai...
Definition: InterfaceUnit.cpp:15743
TTrack::WriteGraphicsToImage
void WriteGraphicsToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by SaveImageNoGridMenuItemClick, SaveImageAndGridMenuItemClick amd SaveImageAndPrefDirsMenuIte...
Definition: TrackUnit.cpp:3711
TInterface::AddText
@ AddText
Definition: InterfaceUnit.h:881
TTrack::PlotPastedTrackElementWithAttributes
void PlotPastedTrackElementWithAttributes(int Caller, TTrackElement TempTrackElement, int HLocInput, int VLocInput, bool &TrackLinkingRequiredFlag, bool InternalChecks)
new at v2.2.0 - as PlotAndAddTrackElement but keeping speed & length attributes (for pasting) and als...
Definition: TrackUnit.cpp:2058
TTrainController::UnexpectedExits
int UnexpectedExits
Definition: TrainUnit.h:774
TInterface::LoadTimetableMenuItemClick
void __fastcall LoadTimetableMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9675
TInterface::LengthEditKeyUp
void __fastcall LengthEditKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11510
TOnePrefDir::EveryPrefDirMarker
void EveryPrefDirMarker(int Caller, TDisplay *Disp)
Similar to PrefDirMarker but used only to mark EveryPrefDir - red for unidirectional PrefDir & green ...
Definition: TrackUnit.cpp:11156
TInterface::OutputLog1
TLabel * OutputLog1
Definition: InterfaceUnit.h:292
TTrain::LeavingUnderSigControlAtContinuation
bool LeavingUnderSigControlAtContinuation
set when the train has reached an exit continuation when under signaller control, used to prevent the...
Definition: TrainUnit.h:355
TInterface::SpeedButton84
TSpeedButton * SpeedButton84
Definition: InterfaceUnit.h:588
TInterface::SpeedButton77
TSpeedButton * SpeedButton77
Definition: InterfaceUnit.h:581
TInterface::SpeedButton128
TSpeedButton * SpeedButton128
Definition: InterfaceUnit.h:632
TTrack::SetTrackFinished
void SetTrackFinished(bool Value)
Definition: TrackUnit.h:842
TTrack::GetInactiveTrackElementFromTrackMap
TTrackElement & GetInactiveTrackElementFromTrackMap(int Caller, int HLoc, int VLoc)
Return a reference to the inactive element at HLoc & VLoc, if no element is found an error is thrown.
Definition: TrackUnit.cpp:5130
TInterface::AddSubMinsBox
TEdit * AddSubMinsBox
the edit box that accepts minutes to add or subtract
Definition: InterfaceUnit.h:175
TAllRoutes::LoadRoutes
bool LoadRoutes(int Caller, std::ifstream &InFile)
Loads the routes from a session file.
Definition: TrackUnit.cpp:17517
TInterface::TTClockExitButton
TButton * TTClockExitButton
Definition: InterfaceUnit.h:218
TInterface::SpeedEditBox2
TEdit * SpeedEditBox2
Definition: InterfaceUnit.h:101
TInterface::MoveForwardsMenuItemClick
void __fastcall MoveForwardsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9961
TTrack::Down
@ Down
Definition: TrackUnit.h:523
TTrainController::TwoOrMoreLocationsWarningGiven
bool TwoOrMoreLocationsWarningGiven
new at v2.6.0 to allow loops
Definition: TrainUnit.h:734
TInterface::TimetableNameLabel
TLabel * TimetableNameLabel
displays the current timetable name on the timetable edit panel
Definition: InterfaceUnit.h:311
TInterface::SpeedButton79
TSpeedButton * SpeedButton79
Definition: InterfaceUnit.h:583
TInterface::SpeedBottomLabel2
TLabel * SpeedBottomLabel2
Definition: InterfaceUnit.h:112
TInterface::SpeedButton51
TSpeedButton * SpeedButton51
Definition: InterfaceUnit.h:555
TInterface::IsPerformancePanelObscuringFloatingLabel
bool IsPerformancePanelObscuringFloatingLabel(int Caller)
Checked during operation, returns true if so and PerformancePanel removed - not used from v2....
Definition: InterfaceUnit.cpp:15586
TimeTimeLoc
@ TimeTimeLoc
Definition: TrainUnit.h:62
TOneRoute::ReqPosRouteID
IDInt ReqPosRouteID
session saves as routes in build are not saved in sessions
Definition: TrackUnit.h:1398
TInterface::TimetableChangedInAZOrderFlag
bool TimetableChangedInAZOrderFlag
used to give a warning message that changes will be discarded if proceed
Definition: InterfaceUnit.h:995
TTrack::PlotRaisedLinkedLevelCrossingBarriers
void PlotRaisedLinkedLevelCrossingBarriers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, TDisplay *Disp)
Plot & close (to trains) all level crossings linked to TrackElement - always plots as red - auto.
Definition: TrackUnit.cpp:6331
TInterface::AddTrackButtonClick
void __fastcall AddTrackButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:864
TInterface::SpeedButton92
TSpeedButton * SpeedButton92
Definition: InterfaceUnit.h:596
TInterface::DeleteMenuItemClick
void __fastcall DeleteMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9533
TTrain::Derailed
bool Derailed
Definition: TrainUnit.h:427
TInterface::ConflictAnalysisButton
TButton * ConflictAnalysisButton
Definition: InterfaceUnit.h:233
TTextHandler::TextVectorPush
void TextVectorPush(int Caller, TTextItem Text)
push &Text onto TextVector & reset the size of the railway if necessary
Definition: TextUnit.cpp:485
TInterface::TTClockAdjButton
TBitBtn * TTClockAdjButton
Definition: InterfaceUnit.h:204
TInterface::PowerEditBoxKeyUp
void __fastcall PowerEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11377
TOneRoute::TRouteFlash::PlotRouteOriginal
void PlotRouteOriginal(int Caller)
display the original (non route-coloured) graphic
Definition: TrackUnit.cpp:15987
TTrack::ResetLevelCrossings
void ResetLevelCrossings(int Caller)
Set all LC attributes to 0 (closed to trains)
Definition: TrackUnit.cpp:6695
TTrainController::SaveSessionLockedRoutes
void SaveSessionLockedRoutes(int Caller, std::ofstream &SessionFile)
save locked routes to a session file
Definition: TrainUnit.cpp:14081
TInterface::OpenHelpMenuItemClick
void __fastcall OpenHelpMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11146
TTrain::OriginalPowerAtRail
double OriginalPowerAtRail
new at v2.4.0 to store value before a failure so it can be restored from here when repaired
Definition: TrainUnit.h:396
TInterface::CheckPerformanceFile
bool CheckPerformanceFile(int Caller, std::ifstream &InFile)
Check the performance file embedded within a session file & return false for error,...
Definition: InterfaceUnit.cpp:17576
TInterface::TInterface
__fastcall TInterface(TComponent *Owner)
constructor
Definition: InterfaceUnit.cpp:80
TInterface::SpeedButton15
TSpeedButton * SpeedButton15
Definition: InterfaceUnit.h:519
clB4G5R5
#define clB4G5R5
Definition: GraphicUnit.h:244
Timetable
@ Timetable
Definition: TrainUnit.h:56
TUtilities::SaveFileDouble
void SaveFileDouble(std::ofstream &OutFile, double SaveDouble)
converts the double value to a string (if double stored directly it is truncated to 6 digits) then st...
Definition: Utilities.cpp:123
TInterface
Definition: InterfaceUnit.h:56
TInterface::RemoveTrainMenuItemClick
void __fastcall RemoveTrainMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10283
TInterface::RotRightMenuItemClick
void __fastcall RotRightMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9142
TTrain::AbleToMoveButForSignal
bool AbleToMoveButForSignal(int Caller)
Indicates that a train is only prevented from moving by a signal - used to allow appropriate popup me...
Definition: TrainUnit.cpp:6331
TTrainController::OpActionPanelVisible
bool OpActionPanelVisible
new v2.2.0 flag to prevent time to act functions when not visible
Definition: TrainUnit.h:732
TInterface::SaveInterface
void SaveInterface(int Caller, std::ofstream &SessionFile)
Save interface part of a session file.
Definition: InterfaceUnit.cpp:16202
TInterface::AcceptDragging
void __fastcall AcceptDragging(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept)
Definition: InterfaceUnit.cpp:5500
Parapet
@ Parapet
Definition: TrackUnit.h:64
TTrack::GapFlashRedPosition
int GapFlashRedPosition
TrackVectorPosition of the gap element that is flashing green or red.
Definition: TrackUnit.h:670
HiddenDisplay
TDisplay * HiddenDisplay
The object pointer for the internal hidden display, object created in InterfaceUnit.
Definition: DisplayUnit.cpp:54
TAllRoutes::GetFixedRouteAt
const TOneRoute & GetFixedRouteAt(int Caller, int At) const
Returns a constant reference to the route at AllRoutesVector position 'At', after performing range ch...
Definition: TrackUnit.cpp:16012
TUtilities::clTransparent
TColor clTransparent
the display background colour, can be white, black or dark blue
Definition: Utilities.h:65
TInterface::RouteFlashDuration
float RouteFlashDuration
duration of the route flash period
Definition: InterfaceUnit.h:1037
TInterface::SpeedButton4
TSpeedButton * SpeedButton4
Definition: InterfaceUnit.h:508
TTrainController::SignalStopWarning
bool SignalStopWarning
Definition: TrainUnit.h:724
TPrefDirElement::GetELinkPos
int GetELinkPos() const
Returns the ELink array position.
Definition: TrackUnit.h:277
TTrack::CheckLocationNameMultiMap
void CheckLocationNameMultiMap(int Caller)
Validity test.
Definition: TrackUnit.cpp:8120
TOneRoute::TRouteFlash::PlotRouteOverlay
void PlotRouteOverlay(int Caller)
display the overlay (route-coloured) graphic
Definition: TrackUnit.cpp:15962
TDisplay::PerformanceLog
void PerformanceLog(int Caller, AnsiString Statement)
Send Statement to the performance log on screen and to the file.
Definition: DisplayUnit.cpp:447
TTrain::SignallerStopBrakeRate
double SignallerStopBrakeRate
the train brake rate when stopping under signaller control
Definition: TrainUnit.h:391
TTrainController::SignallerTrainRemovedOnAutoSigsRoute
bool SignallerTrainRemovedOnAutoSigsRoute
true if train was on an AutoSigsRoute when removed by the signaller
Definition: TrainUnit.h:730
TTrack::InactiveTrackVector
TTrackVector InactiveTrackVector
Definition: TrackUnit.h:707
TTrainController::MRSLow
bool MRSLow
Definition: TrainUnit.h:738
TTrack::ActiveTrackElementNameMap
TActiveTrackElementNameMap ActiveTrackElementNameMap
map of active track element names
Definition: TrackUnit.h:682
TTrain::Crashed
bool Crashed
Definition: TrainUnit.h:427
TInterface::SpeedButton44
TSpeedButton * SpeedButton44
Definition: InterfaceUnit.h:548
TTrackElement::HLoc
int HLoc
Definition: TrackUnit.h:145
TInterface::ScreenRightButton
TBitBtn * ScreenRightButton
Definition: InterfaceUnit.h:249
TTrain::HeadCodePosition
Graphics::TBitmap * HeadCodePosition[4]
Set from the HeadCodeGrPtr[4] pointer values, HeadCodePosition[0] is always the front,...
Definition: TrainUnit.h:441
TInterface::SigPrefButtonClick
void __fastcall SigPrefButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2090
TInterface::OAListBox
TListBox * OAListBox
Operator action list, sits inside OperatorActionPanel and lists trains in ascending order of time to ...
Definition: InterfaceUnit.h:406
TTrain::TrainID
int TrainID
the train's identification number
Definition: TrainUnit.h:330
TInterface::SaveTTButton
TButton * SaveTTButton
Definition: InterfaceUnit.h:145
TUtilities::CheckStringDouble
bool CheckStringDouble(AnsiString &DoubleString)
checks the string represents a valid double value, returns true for success. Added at v2....
Definition: Utilities.cpp:327
TInterface::SpeedButton63
TSpeedButton * SpeedButton63
Definition: InterfaceUnit.h:567
TRailGraphics::bmLightBlueRect
Graphics::TBitmap * bmLightBlueRect
Definition: GraphicUnit.h:522
TInterface::NonSigRouteStartMarker
TGraphicElement * NonSigRouteStartMarker
Definition: InterfaceUnit.h:1118
clB3G3R3
#define clB3G3R3
Definition: GraphicUnit.h:186
TInterface::SpeedButton53
TSpeedButton * SpeedButton53
Definition: InterfaceUnit.h:557
TInterface::SpeedButton107
TSpeedButton * SpeedButton107
Definition: InterfaceUnit.h:611
TTrainController::TrainVectorAt
TTrain & TrainVectorAt(int Caller, int VecPos)
Return a reference to the train at position VecPos in the TrainVector, carries out range checking on ...
Definition: TrainUnit.cpp:14357
TInterface::EditMenuClick
void __fastcall EditMenuClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8805
TTrackElement::LCPlotted
bool LCPlotted
Utility marker to avoid plotting every element of a multitrack LC during ClearandRebuildRailway.
Definition: TrackUnit.h:135
TOnePrefDir::PrefDirMarker
void PrefDirMarker(int Caller, TPrefDirRoute PrefDirRoute, bool BuildingPrefDir, TDisplay *Disp) const
PrefDir and route track marker, including direction markers.
Definition: TrackUnit.cpp:11083
TInterface::ModeMenu
TMenuItem * ModeMenu
Definition: InterfaceUnit.h:419
TInterface::SpeedButton112
TSpeedButton * SpeedButton112
Definition: InterfaceUnit.h:616
TInterface::MTBFEditBoxClick
void __fastcall MTBFEditBoxClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12208
TInterface::TEVPtr
TTEVPtr TEVPtr
Definition: InterfaceUnit.h:1141
TInterface::MasterClock
TTimer * MasterClock
the program clock (not the timetable clock)
Definition: InterfaceUnit.h:499
TInterface::OutputLog6MouseDown
void __fastcall OutputLog6MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11075
TRailGraphics::SpeedBut70GrndBlackGlyph
Graphics::TBitmap * SpeedBut70GrndBlackGlyph
Definition: GraphicUnit.h:1054
TTrainController::NumFailures
int NumFailures
Definition: TrainUnit.h:775
TInterface::CreateEditTTTitle
AnsiString CreateEditTTTitle
the title of the timetable currently being edited - i.e. the filename without the '....
Definition: InterfaceUnit.h:902
TInterface::AboutMenuItemClick
void __fastcall AboutMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11125
TInterface::SelectStartPair
THVPair SelectStartPair
'Select' menu items
Definition: InterfaceUnit.h:1120
TTrainController::TOpTimeToActMultiMapIterator
TOpTimeToActMultiMap::iterator TOpTimeToActMultiMapIterator
Definition: TrainUnit.h:716
TInterface::SpeedButton6
TSpeedButton * SpeedButton6
Definition: InterfaceUnit.h:510
TTrack
Definition: TrackUnit.h:463
TInterface::OperatorActionPanelStartDrag
void __fastcall OperatorActionPanelStartDrag(TObject *Sender, TDragObject *&DragObject)
Definition: InterfaceUnit.cpp:5575
TTrack::TwoAspectBuild
@ TwoAspectBuild
Definition: TrackUnit.h:754
TInterface::OperateRailwayMenuItem
TMenuItem * OperateRailwayMenuItem
Definition: InterfaceUnit.h:424
TInterface::SaveRailwayTBPButton
TBitBtn * SaveRailwayTBPButton
Save button on TrackBuildPanel.
Definition: InterfaceUnit.h:73
TTrain::ExitSpeedFull
double ExitSpeedFull
speed when leaving the next element
Definition: TrainUnit.h:379
TInterface::MTBFLabel
TLabel * MTBFLabel
Definition: InterfaceUnit.h:482
TInterface::SelectBitmap
Graphics::TBitmap * SelectBitmap
the graphic defined by Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1042
TInterface::PreventGapOffsetResetting
bool PreventGapOffsetResetting
during gap setting gaps are highlighted in turn for the user to select the matching gap,...
Definition: InterfaceUnit.h:961
TInterface::TakeSignallerControlMenuItem
TMenuItem * TakeSignallerControlMenuItem
Definition: InterfaceUnit.h:460
clB5G5R5
#define clB5G5R5
Definition: GraphicUnit.h:286
TInterface::Pasting
@ Pasting
Definition: InterfaceUnit.h:882
TInterface::AddTextButton
TBitBtn * AddTextButton
Definition: InterfaceUnit.h:66
TInterface::LoadRailwayMenuItem
TMenuItem * LoadRailwayMenuItem
Definition: InterfaceUnit.h:410
TUtilities::TimeStamp
AnsiString TimeStamp()
creates a string of the form 'hh:mm:ss' for use in call & event logging
Definition: Utilities.cpp:73
TInterface::CrashImage
TImage * CrashImage
Definition: InterfaceUnit.h:263
TTrainController::RandomFailureCounter
unsigned int RandomFailureCounter
Definition: TrainUnit.h:790
TInterface::SpeedButton123
TSpeedButton * SpeedButton123
Definition: InterfaceUnit.h:627
TInterface::USERGRAPHICS_DIR_NAME
static const UnicodeString USERGRAPHICS_DIR_NAME
Definition: InterfaceUnit.h:868
TInterface::mbLeftDown
bool mbLeftDown
true when the left mouse button is down
Definition: InterfaceUnit.h:951
TInterface::SpeedButton115
TSpeedButton * SpeedButton115
Definition: InterfaceUnit.h:619
TInterface::ProgramVersion
UnicodeString ProgramVersion
Definition: InterfaceUnit.h:854
TInterface::TTClockResetButton
TButton * TTClockResetButton
Definition: InterfaceUnit.h:219
TUtilities::CheckAndReadFileInt
bool CheckAndReadFileInt(std::ifstream &InFile, int Lowest, int Highest, int &OutInt)
checks that the value is an int lying between Lowest & Highest (inclusive), returns true for success ...
Definition: Utilities.cpp:251
TInterface::TempCursor
TCursor TempCursor
stores the screen cursor while a temporary cursor (ususlly an hourglass) is displayed
Definition: InterfaceUnit.h:1107
Interface
TInterface * Interface
Definition: InterfaceUnit.cpp:67
TInterface::SpeedButton61
TSpeedButton * SpeedButton61
Definition: InterfaceUnit.h:565
TDisplay::HideWarningLog
void HideWarningLog(int Caller)
Hide all the warnings from the top part of the screen - for timetable clock adjustment.
Definition: DisplayUnit.cpp:475
TTrackElement::ActiveTrackElementName
AnsiString ActiveTrackElementName
Location name used either in the timetable or for a continuation (continuation names not used in time...
Definition: TrackUnit.h:126
TUtilities::DecimalPoint
char DecimalPoint
added at v2.4.0 so can use the local value in loaded session files
Definition: Utilities.h:45
TInterface::ConstructPrefDir
TOnePrefDir * ConstructPrefDir
the Pref Dir under construction
Definition: InterfaceUnit.h:1127
TInterface::SpeedButton81
TSpeedButton * SpeedButton81
Definition: InterfaceUnit.h:585
TInterface::SigsOnLeftImage1
TImage * SigsOnLeftImage1
Definition: InterfaceUnit.h:280
TInterface::BuildTrackMenuItemClick
void __fastcall BuildTrackMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:847
TTrack::LoadTrack
void LoadTrack(int Caller, std::ifstream &VecFile, bool &GraphicsFollow)
Load track elements (active & inactive) from the file into the relevant vectors and maps,...
Definition: TrackUnit.cpp:2596
TInterface::ClearandRebuildRailway
void ClearandRebuildRailway(int Caller)
Clear screen and rebuild it from stored data, uses HiddenScreen to avoid flicker.
Definition: InterfaceUnit.cpp:12426
TInterface::DisplayOneTTLineInPanel
void DisplayOneTTLineInPanel(int Caller, AnsiString Data, bool ServiceEntry)
Display a line from the TimetableEditVector (consists of a series of AnsiStrings, each of which repre...
Definition: InterfaceUnit.cpp:5280
TInterface::PlanPrefDirsMenuItem
TMenuItem * PlanPrefDirsMenuItem
Definition: InterfaceUnit.h:421
TInterface::AreAnyTimesInCurrentEntry
bool AreAnyTimesInCurrentEntry()
Search the timetable entry pointed to by TTCurrentEntryPtr and if any times (HH:MM) are present retur...
Definition: InterfaceUnit.cpp:5360
TTrainController::LogEvent
void LogEvent(AnsiString Str)
store Str to the event log - moved from TUtilities for v0.6 so can record the tt clock value
Definition: TrainUnit.cpp:7940
TInterface::AutoRouteStartMarker
TGraphicElement * AutoRouteStartMarker
Definition: InterfaceUnit.h:1118
TInterface::RestoreTTButtonClick
void __fastcall RestoreTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4402
TInterface::SaveTTButtonClick
void __fastcall SaveTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4020
TInterface::FormCreate
void __fastcall FormCreate(TObject *Sender)
Definition: InterfaceUnit.cpp:743
TGraphicElement::SetSourceRect
void SetSourceRect(int Left, int Top)
Set SourceRect member values from those supplied and existing Width & Height - ensure this is only ca...
Definition: TrackUnit.h:373
TTrack::SelectPush
void SelectPush(TTrackElement TrackElement)
Store a TrackElement in the SelectVector.
Definition: TrackUnit.h:821
TAllRoutes::SignallerRemovedTrainAutoRoute
TOneRoute SignallerRemovedTrainAutoRoute
if train was on an AutoSigsRoute when removed then this stores the route so that signals can be reset
Definition: TrackUnit.h:1584
TInterface::SpeedButton7
TSpeedButton * SpeedButton7
Definition: InterfaceUnit.h:511
TTrainController::MassHigh
bool MassHigh
Definition: TrainUnit.h:738
TInterface::TimetablePanel
TPanel * TimetablePanel
'Create a timetable'/'Edit a timetable' panel that contains the topmost buttons (show/hide & exit)
Definition: InterfaceUnit.h:361
TTrack::PlotAndAddTrackElement
void PlotAndAddTrackElement(int Caller, int CurrentTag, int Aspect, int HLocInput, int VLocInput, bool &TrackPlottedFlag, bool InternalChecks)
Called during track building or pasting, when an element identified by CurrentTag (i....
Definition: TrackUnit.cpp:1823
TTrain::PlotTrainWithNewBackgroundColour
void PlotTrainWithNewBackgroundColour(int Caller, TColor NewBackgroundColour, TDisplay *Disp)
Changes the train's background colour (e.g. to pale green if stopped at a station) Note that this use...
Definition: TrainUnit.cpp:3263
TInterface::LoadSessionMenuItem
TMenuItem * LoadSessionMenuItem
Definition: InterfaceUnit.h:414
TInterface::SpeedButton69
TSpeedButton * SpeedButton69
Definition: InterfaceUnit.h:573
TUtilities::SaveFileString
void SaveFileString(std::ofstream &OutFile, AnsiString SaveString)
stores the string value to the file, then a '0' delimiter then a CR
Definition: Utilities.cpp:131
TInterface::OutputLog5MouseDown
void __fastcall OutputLog5MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11066
TInterface::ErrorButton
TBitBtn * ErrorButton
the 'Press to exit' button on the error screen
Definition: InterfaceUnit.h:257
TInterface::SpeedButton24
TSpeedButton * SpeedButton24
Definition: InterfaceUnit.h:528
TInterface::WarningFlash
bool WarningFlash
toggles on and off automatically at a cycle of about 0.5 sec, used to drive the warning icons during ...
Definition: InterfaceUnit.h:1001
TInterface::CurrentSpeedButton
TSpeedButton * CurrentSpeedButton
stores the selected track build element button during railway building
Definition: InterfaceUnit.h:1138
TInterface::MainScreenMouseDown
void __fastcall MainScreenMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:5596
TTrain::ExitTimeFull
TDateTime ExitTimeFull
times used in SetTrainMovementValues corresponding to the next element the train runs on
Definition: TrainUnit.h:409
TTrackElement::TwoAspect
@ TwoAspect
Definition: TrackUnit.h:156
TTrack::GapFlashRed
TGraphicElement * GapFlashRed
the red & green circle graphics used to show where the gaps are
Definition: TrackUnit.h:690
TInterface::TotalTicks
unsigned int TotalTicks
total clock ticks
Definition: InterfaceUnit.h:1048
TTrack::TryToConnectTrack
bool TryToConnectTrack(int Caller, bool &LocError, int &HLoc, int &VLoc, bool GiveMessages)
Handles all tasks associated with track linking, returns true if successful (see also LinkTrack & Lin...
Definition: TrackUnit.cpp:2281
TInterface::SpeedTopLabel2
TLabel * SpeedTopLabel2
Definition: InterfaceUnit.h:111
SignallerChangeDirection
@ SignallerChangeDirection
Definition: TrainUnit.h:51
TRailGraphics::GridBitmap
Graphics::TBitmap * GridBitmap
Definition: GraphicUnit.h:899
TInterface::PowerBottomLabel
TLabel * PowerBottomLabel
Definition: InterfaceUnit.h:189
TInterface::PasteMenuItem
TMenuItem * PasteMenuItem
Definition: InterfaceUnit.h:437
TTextHandler::EnterAndDisplayNewText
void EnterAndDisplayNewText(int Caller, TTextItem Text, int HPos, int VPos)
add Text to TextVector and display it on the screen
Definition: TextUnit.cpp:179
TOnePrefDir::EndPossible
bool EndPossible(int Caller, bool &LeadingPoints)
Used when setting preferred directions, true if able to finish at the last selected element (can't fi...
Definition: TrackUnit.cpp:10871
TInterface::CreateEditTTFileName
AnsiString CreateEditTTFileName
the full path and filename of the timetable file
Definition: InterfaceUnit.h:900
TOnePrefDir::ConsolidatePrefDirs
void ConsolidatePrefDirs(int Caller, TOnePrefDir *InputPrefDir)
Used when a preferred direction has been set to add all the elements to EveryPrefDir,...
Definition: TrackUnit.cpp:11628
TInterface::PerformanceLogButtonClick
void __fastcall PerformanceLogButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2186
TTrainController::CheckSessionContinuationAutoSigEntries
bool CheckSessionContinuationAutoSigEntries(int Caller, std::ifstream &SessionFile)
Part of the session file integrity check for ContinuationAutoSigEntries, true for success.
Definition: TrainUnit.cpp:14203
IDInt
Definition: TrackUnit.h:412
TInterface::SelectLengthsMenuItemClick
void __fastcall SelectLengthsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9552
TInterface::NewSelectBitmapHLoc
int NewSelectBitmapHLoc
the new (during & at end of moving) HLoc value of Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1056
TInterface::LoadUserGraphic
void LoadUserGraphic(int Caller)
Load a user-defined graphic (bmp, gif, jpg, png).
Definition: InterfaceUnit.cpp:18558
TInterface::TTCurrentEntryPtr
TTEVPtr TTCurrentEntryPtr
Definition: InterfaceUnit.h:1141
TRunningEntry
TRunningEntry
contains status info for each train
Definition: TrainUnit.h:79
TInterface::OutputLog6
TLabel * OutputLog6
Definition: InterfaceUnit.h:297
TUtilities
Definition: Utilities.h:36
TTrack::FindAndHighlightAnUnsetGap
bool FindAndHighlightAnUnsetGap(int Caller)
True if there is an unset gap, and if so it is marked with a red circle, used during gap setting.
Definition: TrackUnit.cpp:3980
TInterface::CreateTimetableMenuItemClick
void __fastcall CreateTimetableMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3058
TInterface::ExportTTButtonClick
void __fastcall ExportTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4485
TDisplay
Definition: DisplayUnit.h:48
TInterface::SpeedButton9
TSpeedButton * SpeedButton9
Definition: InterfaceUnit.h:513
TInterface::TTClockxEighthButtonClick
void __fastcall TTClockxEighthButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11800
TTrack::PlotSmallRailway
void PlotSmallRailway(int Caller, TDisplay *Disp)
Plot on screen the zoomed-out railway.
Definition: TrackUnit.cpp:9101
TTrackElement::ConnLinkPos
int ConnLinkPos[4]
Connecting element link position (i.e. array positions of the connecting element links,...
Definition: TrackUnit.h:143
TTrainController::ContinuationAutoSigVector
TContinuationAutoSigVector ContinuationAutoSigVector
vector for TContinuationAutoSigEntry objects
Definition: TrainUnit.h:792
TInterface::Text_X
int Text_X
the 'X' pixel value for an item of text
Definition: InterfaceUnit.h:1090
TInterface::SpeedVariableLabel
TLabel * SpeedVariableLabel
Definition: InterfaceUnit.h:182
TInterface::SpeedButton49
TSpeedButton * SpeedButton49
Definition: InterfaceUnit.h:553
TTrain::StoppedWithoutPower
bool StoppedWithoutPower
Definition: TrainUnit.h:428
TInterface::PowerVariableLabel
TLabel * PowerVariableLabel
Definition: InterfaceUnit.h:190
TActionEventType
TActionEventType
Used for reporting error conditions & warnings.
Definition: TrainUnit.h:39
TInterface::GapsNotSetImage
TImage * GapsNotSetImage
Definition: InterfaceUnit.h:277
TInterface::Level1Mode
enum TInterface::TLevel1Mode Level1Mode
TInterface::CallLogTickerLabel
TLabel * CallLogTickerLabel
diagnostic label displaying the call log depth, made visible by ctrl+ alt+ 2
Definition: InterfaceUnit.h:319
TInterface::TimetableEditVector
TTimetableEditVector TimetableEditVector
Definition: InterfaceUnit.h:1144
TTrainController::TrainExistsAtIdent
bool TrainExistsAtIdent(int Caller, int TrainID)
new at v2.4.0 return true if find the train (added at v2.4.0 as can select a removed train in OAListB...
Definition: TrainUnit.cpp:8640
SignallerJoin
@ SignallerJoin
Definition: TrainUnit.h:50
TTrain::StepForwardFlag
bool StepForwardFlag
set when the signaller command to step forward one element has been given
Definition: TrainUnit.h:363
TInterface::SaveRailwayDialog
TSaveDialog * SaveRailwayDialog
Definition: InterfaceUnit.h:494
TInterface::TTClockAdjustWarningPanel
TPanel * TTClockAdjustWarningPanel
Definition: InterfaceUnit.h:213
TInterface::TrainTTInfoOnOffMenuItemClick
void __fastcall TrainTTInfoOnOffMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5475
TFixedTrackPiece::Config
TConfiguration Config[4]
the type of link - see TConfiguration above
Definition: TrackUnit.h:95
TTrainController::Operate
void Operate(int Caller)
called every clock tick to introduce new trains and update existing trains
Definition: TrainUnit.cpp:7952
TTrackElement::TrainIDOnElement
int TrainIDOnElement
Definition: TrackUnit.h:151
TRailGraphics::smRed
Graphics::TBitmap * smRed
Definition: GraphicUnit.h:885
TTrain::PowerAtRail
double PowerAtRail
in Watts (taken as 80% of the train's Gross Power, i.e. that entered by the user)
Definition: TrainUnit.h:394
TTrack::FlipArray
int FlipArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'flipping' via menu items 'Edit' & 'Flip'
Definition: TrackUnit.h:668
TAllRoutes::LevelCrossingBarrierDownDelay
const float LevelCrossingBarrierDownDelay
the full value in seconds for which the level crossing flashes prior to opening to trains
Definition: TrackUnit.h:1572
TAllRoutes::RebuildRailwayFlag
bool RebuildRailwayFlag
this is set whenever a route has to be cancelled forcibly in order to force a ClearandRebuildRailway ...
Definition: TrackUnit.h:1565
TUtilities::LoadFileInt
int LoadFileInt(std::ifstream &InFile)
loads an int value from the file
Definition: Utilities.cpp:154
TInterface::SetSaveMenuAndButtons
void SetSaveMenuAndButtons(int Caller)
Called during the ClockTimer2 function to set screen boundaries, buttons & menu items.
Definition: InterfaceUnit.cpp:15211
TTrack::SignalAspectBuildMode
enum TTrack::@2 SignalAspectBuildMode
aspect mode for future signal additions
TInterface::TIMETABLE_DIR_NAME
static const UnicodeString TIMETABLE_DIR_NAME
Definition: InterfaceUnit.h:863
TTrackElement::ElementID
AnsiString ElementID
the element identifier based on position in the railway
Definition: TrackUnit.h:128
TInterface::SaveImageAndPrefDirsMenuItem
TMenuItem * SaveImageAndPrefDirsMenuItem
Definition: InterfaceUnit.h:453
TInterface::LoadRailwayMenuItemClick
void __fastcall LoadRailwayMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2271
TTrack::CheckMapAndInactiveTrack
void CheckMapAndInactiveTrack(int Caller)
Validity test.
Definition: TrackUnit.cpp:6939
TInterface::FormKeyUp
void __fastcall FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11016
TInterface::CopyTTEntryKeyFlag
bool CopyTTEntryKeyFlag
Definition: InterfaceUnit.h:1016
TTrainDataEntry::TrainOperatingDataVector
TTrainOperatingDataVector TrainOperatingDataVector
operating information for the train including all its repeats
Definition: TrainUnit.h:197
TInterface::OutputLog9MouseDown
void __fastcall OutputLog9MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11105
TTrack::TActiveLevelCrossing::StartTime
TDateTime StartTime
stores the starting time for level crossing changing
Definition: TrackUnit.h:544
TTrackElement::VLoc
int VLoc
The h & v locations in the railway (top lh corner of the first build screen = 0,0)
Definition: TrackUnit.h:145
TTrack::GetNonPointsOppositeLinkPos
int GetNonPointsOppositeLinkPos(int LinkPosIn)
Return the corresponding link position (track always occupies either links 0 & 1 or 2 & 3)
Definition: TrackUnit.h:788
TOneRoute::TRouteFlash::RouteFlashVector
std::vector< TRouteFlashElement > RouteFlashVector
Definition: TrackUnit.h:1384
TInterface::SpeedButton80
TSpeedButton * SpeedButton80
Definition: InterfaceUnit.h:584
TTrain::IsThereAnAdjacentTrain
bool IsThereAnAdjacentTrain(int Caller, TTrain *&TrainToBeJoinedBy)
Definition: TrainUnit.cpp:4710
TInterface::ApproachLocking
void ApproachLocking(int Caller, TDateTime Now)
Function that deals with approach locking during ClockTimer2 function.
Definition: InterfaceUnit.cpp:14203
TInterface::TimetableTitle
AnsiString TimetableTitle
the titles of the loaded railway and loaded timetable, i.e. the filenames without the extension
Definition: InterfaceUnit.h:914
TInterface::BlackBgndMenuItemClick
void __fastcall BlackBgndMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11169
TInterface::SpeedButton114
TSpeedButton * SpeedButton114
Definition: InterfaceUnit.h:618
TInterface::Deleting
@ Deleting
Definition: InterfaceUnit.h:882
TInterface::RestoreAllDefaultLengthsButton
TBitBtn * RestoreAllDefaultLengthsButton
Definition: InterfaceUnit.h:77
TInterface::ClearAllMenuItemClick
void __fastcall ClearAllMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2987
TUtilities::EventLog
std::deque< AnsiString > EventLog
event store, saved to the errorlog for diagnostic purposes
Definition: Utilities.h:57
TInterface::MoveTTEntryUpKeyFlag
bool MoveTTEntryUpKeyFlag
Definition: InterfaceUnit.h:1014
TActionVectorEntry::FormatType
TTimetableFormatType FormatType
defines the timetable action type
Definition: TrainUnit.h:110
TInterface::TextBox
TEdit * TextBox
the edit box that accepts text to be added
Definition: InterfaceUnit.h:88
TGraphicElement::GetHPos
int GetHPos()
Definition: TrackUnit.h:362
TInterface::SpeedButton133
TSpeedButton * SpeedButton133
Definition: InterfaceUnit.h:637
TOnePrefDir::SearchVectorSize
unsigned int SearchVectorSize() const
Return the vector size.
Definition: TrackUnit.h:1277
TTrainController::RestartTime
TDateTime RestartTime
TTClockTime when operation pauses ( = timetable start time prior to operation) TTClockTime is calcula...
Definition: TrainUnit.h:639
TTrainController::TimetableStartTime
TDateTime TimetableStartTime
the start time of the current timetable
Definition: TrainUnit.h:637
TTrainController::UnplotTrains
void UnplotTrains(int Caller)
unplot all trains from screen
Definition: TrainUnit.cpp:8295
TInterface::SpeedButton18
TSpeedButton * SpeedButton18
Definition: InterfaceUnit.h:522
TInterface::ScreenGridFlag
bool ScreenGridFlag
true when the screen grid is displayed
Definition: InterfaceUnit.h:969
TInterface::InfoCaptionStore
AnsiString InfoCaptionStore
temporary store for the information panel caption
Definition: InterfaceUnit.h:908
TRailGraphics::smBrightGreen
Graphics::TBitmap * smBrightGreen
Definition: GraphicUnit.h:877
TInterface::CopiedEntryFlag
bool CopiedEntryFlag
true when CopiedEntryStr holds a timetable entry in the timetable editor
Definition: InterfaceUnit.h:931
TOneRoute::ConvertAndAddPreferredRouteSearchVector
void ConvertAndAddPreferredRouteSearchVector(int Caller, IDInt ReqPosRouteID, bool AutoSigsFlag)
Called after a preferred (i.e. preferred direction or automatic signals) route has been selected and ...
Definition: TrackUnit.cpp:13983
TInterface::SpeedButton89
TSpeedButton * SpeedButton89
Definition: InterfaceUnit.h:593
TTrainController::EarlyArrivals
int EarlyArrivals
Definition: TrainUnit.h:760
TInterface::AnyTTKeyFlagSet
bool AnyTTKeyFlagSet()
Definition: InterfaceUnit.h:1154
TTrainController::CreateFormattedTimetable
void CreateFormattedTimetable(int Caller, AnsiString RailwayTitle, AnsiString TimetableTitle, AnsiString CurDir)
Examines the internal timetable (TrainDataVector) and creates from it a chronological (....
Definition: TrainUnit.cpp:14370
TInterface::SetTopIndex
void SetTopIndex(int Caller)
This used in timetable functions when shift keys pressed to make sure that the highlighted entry rema...
Definition: InterfaceUnit.cpp:12404
TTrack::RouteFlashFlag
bool RouteFlashFlag
true while a route is flashing prior to being set
Definition: TrackUnit.h:657
TOnePrefDir::RealignAfterTrackErase
void RealignAfterTrackErase(int Caller, int ErasedTrackVectorPosition)
After a track element is erased the preferred direction elements are likely to be affected....
Definition: TrackUnit.cpp:12087
TInterface::PowerToggleButtonClick
void __fastcall PowerToggleButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11356
PrefDirCall
@ PrefDirCall
Definition: TrackUnit.h:1182
TTrackElement::StationEntryStopLinkPos1
int StationEntryStopLinkPos1
Definition: TrackUnit.h:149
TInterface::SpeedButton46
TSpeedButton * SpeedButton46
Definition: InterfaceUnit.h:550
Points
@ Points
Definition: TrackUnit.h:63
TTrainController::TotLatePassMins
float TotLatePassMins
Definition: TrainUnit.h:755
TTrainController::StripSpaces
void StripSpaces(int Caller, AnsiString &Input)
Strip both leading and trailing spaces at ends of Input and spaces before and after all commas and se...
Definition: TrainUnit.cpp:12767
TInterface::Delay
void Delay(int Caller, double Msec)
Delays operation for the set time in milliseconds.
Definition: InterfaceUnit.cpp:12809
TTrain::JoinedOtherTrainFlag
bool JoinedOtherTrainFlag
true when the train has joined another train following an 'Fjo' timetable command or a signaller join...
Definition: TrainUnit.h:351
TTrainController::OpActionPanelHintDelayCounter
unsigned int OpActionPanelHintDelayCounter
new v2.2.0 on start operation delays the op action panel headcode display for about 3 secs while hint...
Definition: TrainUnit.h:788
TTrainController::BFLow
bool BFLow
Definition: TrainUnit.h:738
TInterface::OutputLog7
TLabel * OutputLog7
Definition: InterfaceUnit.h:298
TTrainController::TotArrDepPass
int TotArrDepPass
Definition: TrainUnit.h:773
TInterface::LastNonCtrlOrShiftKeyDown
int LastNonCtrlOrShiftKeyDown
value of last key (other than Ctrl or Shift) pressed down - to prevent repeated FormKeyDown calls fro...
Definition: InterfaceUnit.h:1054
SignallerPassRedSignal
@ SignallerPassRedSignal
Definition: TrainUnit.h:51
TRailGraphics::ChangeForegroundColour
void ChangeForegroundColour(int Caller, Graphics::TBitmap *BitmapIn, Graphics::TBitmap *BitmapOut, TColor NewForegroundColour, TColor BackgroundColour)
Definition: GraphicUnit.cpp:3326
TInterface::TextItem
int TextItem
used to store a single item of text
Definition: InterfaceUnit.h:1096
TInterface::UserGraphicButtonClick
void __fastcall UserGraphicButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12230
TInterface::OriginalTimetableEditVector
TTimetableEditVector OriginalTimetableEditVector
the complete timetable as a list of AnsiStrings for use in edit timetable functions
Definition: InterfaceUnit.h:1144
TGraphicElement::LoadOverlayGraphic
void LoadOverlayGraphic(int Caller, Graphics::TBitmap *Overlay)
Load the temporary overlay graphic.
Definition: TrackUnit.cpp:1569
TInterface::PresetAutoSigRoutesButtonClick
void __fastcall PresetAutoSigRoutesButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11938
TRailGraphics::SpeedBut68GrndBlackGlyph
Graphics::TBitmap * SpeedBut68GrndBlackGlyph
Definition: GraphicUnit.h:1052
TTrain::SignallerRemoved
bool SignallerRemoved
set when removed under signaller control to force a removal from the display at the next clock tick
Definition: TrainUnit.h:359
TTrain::FrontCodePtr
Graphics::TBitmap * FrontCodePtr
points to the front headcode segment, this is set to red or blue depending on TrainMode
Definition: TrainUnit.h:445
TOneRoute::SetRouteSignals
void SetRouteSignals(int Caller) const
Called when setting a route to set all points appropriately. Also called when a new train is added at...
Definition: TrackUnit.cpp:15322
Continuation
@ Continuation
Definition: TrackUnit.h:63
TInterface::ScreenUpButton
TBitBtn * ScreenUpButton
Definition: InterfaceUnit.h:251
TInterface::TTServiceSyntaxCheckButton
TButton * TTServiceSyntaxCheckButton
Definition: InterfaceUnit.h:143
TTrainController::CallOnWarning
bool CallOnWarning
Definition: TrainUnit.h:724
TInterface::SetLengthsButton
TBitBtn * SetLengthsButton
Definition: InterfaceUnit.h:71
TUserGraphicItem::Height
int Height
Definition: DisplayUnit.h:35
GraphicUnit.h
TInterface::AppActivate
void __fastcall AppActivate(TObject *Sender)
Definition: InterfaceUnit.cpp:794
TTrack::RebuildTrackAndText
void RebuildTrackAndText(int Caller, TDisplay *Disp, bool BothPointFilletsAndBasicLCs)
Called by TInterface::ClearandRebuildRailway to replot all the active and inactive track elements and...
Definition: TrackUnit.cpp:3341
TextUnit.h
TTrack::PlotPoints
void PlotPoints(int Caller, TTrackElement TrackElement, TDisplay *Disp, bool BothFillets)
Plot points on screen according to how they are set (Attribute value), or, with both fillets if BothF...
Definition: TrackUnit.cpp:5366
TInterface::AddTextButtonClick
void __fastcall AddTextButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1055
TDisplay::DisplayZoomOutOffsetV
static int DisplayZoomOutOffsetV
the verticalal offset of the zoomed-out display
Definition: DisplayUnit.h:86
TInterface::ReselectMenuItemClick
void __fastcall ReselectMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8853
TInterface::SpeedButton94
TSpeedButton * SpeedButton94
Definition: InterfaceUnit.h:598
TInterface::SaveTTAsKeyFlag
bool SaveTTAsKeyFlag
Definition: InterfaceUnit.h:1025
TInterface::SaveTTEntryButtonClick
void __fastcall SaveTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3872
TInterface::TimetablePanelLabel
TLabel * TimetablePanelLabel
label to the left of TimetablePanel
Definition: InterfaceUnit.h:313
TTrack::PointFlashFlag
bool PointFlashFlag
true when points are flashing during manual change
Definition: TrackUnit.h:655
TTrainController::OnTimeDeps
int OnTimeDeps
Definition: TrainUnit.h:768
TTrain::RestoreTimetableLocation
AnsiString RestoreTimetableLocation
stores the location name at which signaller control is taken, to ensure that it is back at that locat...
Definition: TrainUnit.h:419
TInterface::SpeedButton40
TSpeedButton * SpeedButton40
Definition: InterfaceUnit.h:544
TTrainController::TimetableIntegrityCheck
bool TimetableIntegrityCheck(int Caller, char *FileName, bool GiveMessages, bool CheckLocationsExistInRailway)
Checks overall timetable integrity, calls many other specific checking functions, returns true for su...
Definition: TrainUnit.cpp:8987
AllRoutes
TAllRoutes * AllRoutes
the object pointer, object created in InterfaceUnit
Definition: TrackUnit.cpp:54
TDisplay::Left
int Left()
Return the left pixel position of the screen.
Definition: DisplayUnit.h:114
TTrain::SignallerMaxSpeed
int SignallerMaxSpeed
maximum train speed under signaller control (in km/h)
Definition: TrainUnit.h:323
TInterface::BufferAttentionImage
TImage * BufferAttentionImage
Definition: InterfaceUnit.h:261
TOnePrefDir::ValidatePrefDir
bool ValidatePrefDir(int Caller)
Checks that all elements in PrefDirVector have been properly set, i.e. don't have their default value...
Definition: TrackUnit.cpp:10914
TTrainController::SendPerformanceSummary
void SendPerformanceSummary(int Caller, std::ofstream &PerfFile)
At the end of operation a summary of overall performance is sent to the performance file by this func...
Definition: TrainUnit.cpp:16938
TInterface::OperatorActionButtonClick
void __fastcall OperatorActionButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12042
TInterface::SpeedEditBox
TEdit * SpeedEditBox
Definition: InterfaceUnit.h:179
TInterface::LoadRailwayDialog
TOpenDialog * LoadRailwayDialog
Definition: InterfaceUnit.h:488
TInterface::CopyMenuItem
TMenuItem * CopyMenuItem
Definition: InterfaceUnit.h:433
TInterface::ResetDefaultLengthButtonClick
void __fastcall ResetDefaultLengthButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1564
RepairFailedTrain
@ RepairFailedTrain
Definition: TrainUnit.h:51
TInterface::NoOperMode
@ NoOperMode
Definition: InterfaceUnit.h:873
TInterface::ErrorLogCalledFlag
bool ErrorLogCalledFlag
true when an error has been thrown, stops repeated calls to ErrorLog and stops the MasterClockTimer f...
Definition: InterfaceUnit.h:939
TInterface::NextTTEntryKeyFlag
bool NextTTEntryKeyFlag
Definition: InterfaceUnit.h:1013
TInterface::RouteFlashStartTime
TDateTime RouteFlashStartTime
stores the starting time (timetable clock time) for route flashing
Definition: InterfaceUnit.h:1114
TInterface::PerformancePanelLabel
TLabel * PerformancePanelLabel
label at the top of PerformancePanel
Definition: InterfaceUnit.h:303
TInterface::BlueBgndMenuItemClick
void __fastcall BlueBgndMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11221
TInterface::SetTrackLengths
void SetTrackLengths(int Caller, int Distance, int SpeedLimit)
Called during track building when setting distances, to calculate and set the individual track elemen...
Definition: InterfaceUnit.cpp:17999
TInterface::SpeedToggleButtonClick
void __fastcall SpeedToggleButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11247
TTrainController::ContinuationEntryFloatingTTString
AnsiString ContinuationEntryFloatingTTString(int Caller, TTrainDataEntry *TTDEPtr, int RepeatNumber, int IncrementalMinutes, int IncrementalDigits)
Build string for use in floating window for expected trains at continuations.
Definition: TrainUnit.cpp:8671
TTrack::CheckTrackElementsInFile
bool CheckTrackElementsInFile(int Caller, int &NumberOfActiveElements, bool &GraphicsFollow, std::ifstream &VecFile)
True if TrackElements in the file are all valid.
Definition: TrackUnit.cpp:2958
TGraphicElement::GetVPos
int GetVPos()
Definition: TrackUnit.h:367
TOneRoute::StartSelectionRouteID
IDInt StartSelectionRouteID
needed for session saves as routes in build are not saved in sessions
Definition: TrackUnit.h:1401
TFixedTrackPiece::SpeedTag
int SpeedTag
The element identification number - corresponds to the relevant SpeedButton->Tag.
Definition: TrackUnit.h:85
TTrain::SPADFlag
bool SPADFlag
set when running past a red signal without permission flags to indicate relevant stop conditions or p...
Definition: TrainUnit.h:425
TInterface::TTLabel5
TLabel * TTLabel5
Definition: InterfaceUnit.h:343
TInterface::HomeButtonClick
void __fastcall HomeButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8736
TInterface::PointFlashStartTime
TDateTime PointFlashStartTime
stores the starting time (timetable clock time) for points flashing
Definition: InterfaceUnit.h:1112
TInterface::TTLabel7
TLabel * TTLabel7
Definition: InterfaceUnit.h:345
TInterface::RailwayWebSiteMenuItemClick
void __fastcall RailwayWebSiteMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11161
TTrain::Stopped
bool Stopped()
True if the train has stopped for any reason.
Definition: TrainUnit.h:609
TInterface::SpeedButton36
TSpeedButton * SpeedButton36
Definition: InterfaceUnit.h:540
TInterface::TTFirstServicePtr
TTEVPtr TTFirstServicePtr
Definition: InterfaceUnit.h:1141
TInterface::ClockTimer2
void ClockTimer2(int Caller)
The main loop, called every clock tick via MasterClockTimer.
Definition: InterfaceUnit.cpp:7754
TInterface::SpeedButton56
TSpeedButton * SpeedButton56
Definition: InterfaceUnit.h:560
TDisplay::PlotDashedRect
void PlotDashedRect(int Caller, TRect Rect)
Plot a dashed rectangle for the area defined by Rect, used when selecting display areas.
Definition: DisplayUnit.cpp:429
TInterface::NewTTEntryButtonClick
void __fastcall NewTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3447
TInterface::LoadSessionMenuItemClick
void __fastcall LoadSessionMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2973
TTrack::SelectVectorClear
void SelectVectorClear()
Definition: TrackUnit.h:826
TInterface::PerformanceFileName
AnsiString PerformanceFileName
full path and filename of the performance file
Definition: InterfaceUnit.h:912
TInterface::AutoSigsButton
TBitBtn * AutoSigsButton
Definition: InterfaceUnit.h:195
TInterface::PopupMenu
TPopupMenu * PopupMenu
Definition: InterfaceUnit.h:485
TInterface::LoadSessionFlag
bool LoadSessionFlag
true when a session load command has been given - implemented at next clock tick
Definition: InterfaceUnit.h:949
TPrefDirElement::GetELink
int GetELink() const
Returns ELink.
Definition: TrackUnit.h:271
TInterface::NoTrackMode
@ NoTrackMode
Definition: InterfaceUnit.h:881
TInterface::TimetableValidFlag
bool TimetableValidFlag
indicates that a 'Validate timetable' button click in the timetable editor has succeeded
Definition: InterfaceUnit.h:993
TInterface::TimetableControlMenuItem
TMenuItem * TimetableControlMenuItem
Definition: InterfaceUnit.h:461
TUtilities::CheckFileDouble
bool CheckFileDouble(std::ifstream &InFile)
checks that the value is a double, returns true for success
Definition: Utilities.cpp:294
TUtilities::PerformanceFile
std::ofstream PerformanceFile
the file where the performance log for a particular period of operation is saved
Definition: Utilities.h:53
TInterface::TTLabel15
TLabel * TTLabel15
Definition: InterfaceUnit.h:352
TInterface::PreferredRoute
bool PreferredRoute
true when AutoSig or preferred route building selected during operation (always same state as ConsecS...
Definition: InterfaceUnit.h:957
TInterface::ConvertCRLFsToCommas
void ConvertCRLFsToCommas(int Caller, AnsiString &ConvStr)
Used in timetable editing functions to convert any CRLFs in intended service entries to commas.
Definition: InterfaceUnit.cpp:5061
TInterface::OutputLog2MouseDown
void __fastcall OutputLog2MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11037
TDisplay::DisplayZoomOutOffsetH
static int DisplayZoomOutOffsetH
the horizontal offset of the zoomed-out display
Definition: DisplayUnit.h:84
TInterface::SpeedButton106
TSpeedButton * SpeedButton106
Definition: InterfaceUnit.h:610
Display
TDisplay * Display
The object pointer for the on-screen display, object created in InterfaceUnit.
Definition: DisplayUnit.cpp:53
TInterface::LoadTimetableFromSessionFile
bool LoadTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
Loads timetable into memory from a session file, true if successful.
Definition: InterfaceUnit.cpp:16667
TTrack::RotRightArray
int RotRightArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'rotating right' via menu items 'Edit' & 'Rotate right'
Definition: TrackUnit.h:674
TInterface::SpeedButton125
TSpeedButton * SpeedButton125
Definition: InterfaceUnit.h:629
TInterface::SpeedButton21
TSpeedButton * SpeedButton21
Definition: InterfaceUnit.h:525
TUtilities::DateTimeStamp
AnsiString DateTimeStamp()
creates a string of the form 'dd/mm/yyyy hh:mm:ss' for use in call & event logging
Definition: Utilities.cpp:67
TTrack::GetVLocMin
int GetVLocMin()
Definition: TrackUnit.h:782
TTrack::ResetPoints
void ResetPoints(int Caller)
Called on exit from operation to reset all points to non-diverging or to left fork (Attribute = 0)
Definition: TrackUnit.cpp:4229
TInterface::SpeedButton64
TSpeedButton * SpeedButton64
Definition: InterfaceUnit.h:568
TInterface::AllEntriesTTListBoxMouseUp
void __fastcall AllEntriesTTListBoxMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:4684
TAllRoutes::AllRoutesSize
unsigned int AllRoutesSize() const
Returns the number of routes in the railway.
Definition: TrackUnit.h:1592
TInterface::FontButton
TBitBtn * FontButton
Definition: InterfaceUnit.h:69
TTrack::LCVector
TLCVector LCVector
vector of level crossing InactiveTrackVector positions
Definition: TrackUnit.h:694
TInterface::NextTTEntryButtonClick
void __fastcall NextTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3369
TUtilities::CheckFileBool
bool CheckFileBool(std::ifstream &InFile)
checks that the value is a bool returns true for success
Definition: Utilities.cpp:198
TInterface::~TInterface
__fastcall ~TInterface()
destructor
Definition: InterfaceUnit.cpp:684
TInterface::CancelTTEntryButtonClick
void __fastcall CancelTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4365
TInterface::TTEVPtr
std::vector< AnsiString >::iterator TTEVPtr
typedef for pointers to entries in edit timetable functions
Definition: InterfaceUnit.h:892
TInterface::SaveHeaderMenu1Click
void __fastcall SaveHeaderMenu1Click(TObject *Sender)
Definition: InterfaceUnit.cpp:2915
TInterface::TTStartTimePtr
TTEVPtr TTStartTimePtr
Definition: InterfaceUnit.h:1141
TTrack::TActiveTrackElementNameMapEntry
std::pair< AnsiString, int > TActiveTrackElementNameMapEntry
Definition: TrackUnit.h:617
TInterface::TTClockAdjPanel
TPanel * TTClockAdjPanel
Definition: InterfaceUnit.h:212
TInterface::BuildTrainDataVectorForLoadFile
bool BuildTrainDataVectorForLoadFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway, bool SessionFile)
Convert a stored timetable file (either as a stand alone file or within a session file) to a loaded t...
Definition: InterfaceUnit.cpp:16878
TInterface::ConflictPanel
TPanel * ConflictPanel
Definition: InterfaceUnit.h:236
TInterface::CompileAllEntriesMemoAndSetPointers
void CompileAllEntriesMemoAndSetPointers(int Caller)
Used during timetable editing funtions to compile the list of entries into the left hand long entry w...
Definition: InterfaceUnit.cpp:4816
TInterface::CopiedEntryStr
AnsiString CopiedEntryStr
a timetable entry that has been copied
Definition: InterfaceUnit.h:898
TInterface::SpeedButton12
TSpeedButton * SpeedButton12
Definition: InterfaceUnit.h:516
TAllRoutes::SaveRoutes
void SaveRoutes(int Caller, std::ofstream &OutFile)
Save railway route information to a session file or an error file.
Definition: TrackUnit.cpp:17501
TInterface::SelectMenuItem
TMenuItem * SelectMenuItem
Definition: InterfaceUnit.h:430
TInterface::MoveTTEntryDownKeyFlag
bool MoveTTEntryDownKeyFlag
Definition: InterfaceUnit.h:1015
TGraphicElement::PlotOverlay
void PlotOverlay(int Caller, TDisplay *Disp)
Plot the overlay graphic on screen.
Definition: TrackUnit.cpp:1579
TTrack::ResetSignals
void ResetSignals(int Caller)
Called on exit from operation to reset all signals to red (Attribute = 0)
Definition: TrackUnit.cpp:4214
Connection
@ Connection
Definition: TrackUnit.h:73
TInterface::TTTextButtonClick
void __fastcall TTTextButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4524
TTrack::LoadBarriersDownVector
void LoadBarriersDownVector(int Caller, std::ifstream &VecFile)
Load all BarriersDownVector values from SessionFile.
Definition: TrackUnit.cpp:3318
TTrainController::TrainFailedWarning
bool TrainFailedWarning
Flags to enable the relevant warning graphics to flash at the left hand side of the screen.
Definition: TrainUnit.h:724
TAllRoutes::RouteTruncateFlag
bool RouteTruncateFlag
used to flag the fact that a route is being truncated on order to change the behaviour of signal aspe...
Definition: TrackUnit.h:1567
TInterface::LengthOKButton
TBitBtn * LengthOKButton
distance/speed setting buttons - left to right & top to bottom
Definition: InterfaceUnit.h:80
TTrain::NextTrainID
static int NextTrainID
the ID value to be used for the next train that is created, static so that it doesn't need an object ...
Definition: TrainUnit.h:287
TInterface::PreviousTTEntryButtonClick
void __fastcall PreviousTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3408
TInterface::UserGraphicButton
TBitBtn * UserGraphicButton
Definition: InterfaceUnit.h:82
TOneRoute::ConvertAndAddNonPreferredRouteSearchVector
void ConvertAndAddNonPreferredRouteSearchVector(int Caller, IDInt ReqPosRouteID)
Called after a non-preferred (i.e. unrestricted) route has been selected and has finished flashing,...
Definition: TrackUnit.cpp:15132
TInterface::Text_Y
int Text_Y
as above for 'Y'
Definition: InterfaceUnit.h:1092
TAllRoutes::CheckMapAndRoutes
void CheckMapAndRoutes(int Caller)
Diagnostic function - checks equivalence for each route between entries in PrefDirVector and those in...
Definition: TrackUnit.cpp:16803
TInterface::DeleteTTEntryButton
TButton * DeleteTTEntryButton
Definition: InterfaceUnit.h:133
DefaultTrackSpeedLimit
#define DefaultTrackSpeedLimit
Definition: TrackUnit.h:38
TInterface::ReselectUserGraphicClick
void __fastcall ReselectUserGraphicClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12262
TInterface::TTClockAdd1mButtonClick
void __fastcall TTClockAdd1mButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11877
TInterface::SubMinsButton
TButton * SubMinsButton
Definition: InterfaceUnit.h:142
TInterface::SpeedButton66
TSpeedButton * SpeedButton66
Definition: InterfaceUnit.h:570
TTrack::PlotPlainRaisedLinkedLevelCrossingBarriersAndSetMarkers
void PlotPlainRaisedLinkedLevelCrossingBarriersAndSetMarkers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, TDisplay *Disp)
Plot LC elements without any base elements, and set LCPlotted true - used in ClearandRebuildRailway.
Definition: TrackUnit.cpp:6404
TInterface::ValidateTimetableButtonClick
void __fastcall ValidateTimetableButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4185
TInterface::UserGraphicMoveVPos
int UserGraphicMoveVPos
used to store the original user graphic 'H' & 'V' positions for use during moving
Definition: InterfaceUnit.h:1102
TInterface::SpeedButton98
TSpeedButton * SpeedButton98
Definition: InterfaceUnit.h:602
TActionVectorEntry::LocationName
AnsiString LocationName
Definition: TrainUnit.h:96
TInterface::LoadTimetableMenuItem
TMenuItem * LoadTimetableMenuItem
Definition: InterfaceUnit.h:413
TInterface::SpeedButton95
TSpeedButton * SpeedButton95
Definition: InterfaceUnit.h:599
TInterface::LocationNameButtonClick
void __fastcall LocationNameButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1133
TTrack::InactiveTrackElementPresentAtHV
bool InactiveTrackElementPresentAtHV(int Caller, int HLoc, int VLoc)
New at v1.2.0; true if an inactive track element present.
Definition: TrackUnit.cpp:5174
TInterface::SaveMenuItem
TMenuItem * SaveMenuItem
Definition: InterfaceUnit.h:412
TInterface::GapSetting
@ GapSetting
Definition: InterfaceUnit.h:881
TTrain::TimeTimeLocArrived
bool TimeTimeLocArrived
indicates whether has arrived (true) or not when ActionVectorEntryPtr->FormatType == TimeTimeLoc
Definition: TrainUnit.h:294
TInterface::ShowHideTTButton
TBitBtn * ShowHideTTButton
Definition: InterfaceUnit.h:124
TInterface::ScreenDownButton
TBitBtn * ScreenDownButton
Definition: InterfaceUnit.h:252
TTrain::LeadEntryPos
int LeadEntryPos
Definition: TrainUnit.h:327
TTrack::OverrideAndHideSignalBridgeMessage
bool OverrideAndHideSignalBridgeMessage
if false signals facing bridges are not permitted, but can be set to true using CTRL ALT 5
Definition: TrackUnit.h:661
TTrainController::LateArrivals
int LateArrivals
Definition: TrainUnit.h:763
TInterface::DeleteOnePrefDirButton
TBitBtn * DeleteOnePrefDirButton
Definition: InterfaceUnit.h:117
TInterface::PauseEntryTTClockSpeed
float PauseEntryTTClockSpeed
rate at which the timetable clock runs on entry to the adjust routine - to restore if cancelled
Definition: InterfaceUnit.h:1033
TTrainController::ReplotTrains
void ReplotTrains(int Caller, TDisplay *Disp)
plot all trains on the display
Definition: TrainUnit.cpp:8265
TInterface::MetreVariableLabel
TLabel * MetreVariableLabel
Definition: InterfaceUnit.h:103
TInterface::AllEntriesTTListBoxTopPosition
int AllEntriesTTListBoxTopPosition
stores the TopIndex property when keys are used to select items in the TT edit panel
Definition: InterfaceUnit.h:1052
TInterface::SigImagePanel
TPanel * SigImagePanel
new at v2.3.0 for handed signals
Definition: InterfaceUnit.h:387
TTrain::FloatingTimetableString
AnsiString FloatingTimetableString(int Caller, TActionVectorEntry *Ptr)
Used in the floating window to display the timetable.
Definition: TrainUnit.cpp:6588
TTrack::CopyFlag
bool CopyFlag
true only when copying a selection, used to prevent location names being copied
Definition: TrackUnit.h:643
TAllRoutes::GetModifiableRouteAt
TOneRoute & GetModifiableRouteAt(int Caller, int At)
Returns a modifiable reference to the route at AllRoutesVector position 'At', after performing range ...
Definition: TrackUnit.cpp:16026
TInterface::CPGenFileButtonClick
void __fastcall CPGenFileButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12359
TInterface::TTClockAdd10mButtonClick
void __fastcall TTClockAdd10mButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11857
TRailGraphics::SpeedBut73GrndBlackGlyph
Graphics::TBitmap * SpeedBut73GrndBlackGlyph
Definition: GraphicUnit.h:1057
TTrain::AValue
double AValue
this is a useful shorthand value in calculating speeds and transit times in SetTrainMovementValues [=...
Definition: TrainUnit.h:371
TTrack::CheckMapAndTrack
void CheckMapAndTrack(int Caller)
Validity test.
Definition: TrackUnit.cpp:6899
TTrack::LoadGraphics
void LoadGraphics(int Caller, std::ifstream &VecFile, UnicodeString GraphicsPath)
new at v2.4.0, load user graphics
Definition: TrackUnit.cpp:2724
TTrainController::WriteTrainsToImage
void WriteTrainsToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by TInterface::SaveOperatingImage1Click) to write all trains to the image file.
Definition: TrainUnit.cpp:8280
TInterface::SpeedButton30
TSpeedButton * SpeedButton30
Definition: InterfaceUnit.h:534
TTrackElement::LocationName
AnsiString LocationName
location name not used for timetabling, only for identification: platforms, non-station named locatio...
Definition: TrackUnit.h:130
TInterface::TTClockSpeedLabel
TLabel * TTClockSpeedLabel
Definition: InterfaceUnit.h:329
TTrack::FourAspectBuild
@ FourAspectBuild
Definition: TrackUnit.h:754
TInterface::SpeedButton146
TSpeedButton * SpeedButton146
Definition: InterfaceUnit.h:650
TTrainController::OpTimeToActMultiMapIterator
TOpTimeToActMultiMapIterator OpTimeToActMultiMapIterator
added v2.2.0 for Op time to act display
Definition: TrainUnit.h:798
TTrack::TActiveLevelCrossing::HLoc
int HLoc
HLoc value for found level crossing element.
Definition: TrackUnit.h:540
TInterface::NewEntryInPreparationFlag
bool NewEntryInPreparationFlag
true when a new timetable entry is being prepared in the timetable editor
Definition: InterfaceUnit.h:953
TDisplay::DisplayOffsetH
static int DisplayOffsetH
the horizontal offset of the displayed screen
Definition: DisplayUnit.h:76
TInterface::OAPanelLabel
TLabel * OAPanelLabel
Definition: InterfaceUnit.h:334
TInterface::GetVersion
UnicodeString GetVersion()
determined automatically from the project options 'Version Info'
Definition: InterfaceUnit.cpp:811
TInterface::OneEntryTimetableContents
AnsiString OneEntryTimetableContents
the current text in the large right hand timetable edit window
Definition: InterfaceUnit.h:910
TInterface::SelectRect
TRect SelectRect
the rectangle in HLoc & VLoc terms set in Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1135
TTrain::ZeroPowerNoJoinedByMessage
bool ZeroPowerNoJoinedByMessage
Definition: TrainUnit.h:303
TInterface::LocationNameComboBox
TComboBox * LocationNameComboBox
the combobox that lists location names
Definition: InterfaceUnit.h:173
TInterface::ValidateTimetableKeyFlag
bool ValidateTimetableKeyFlag
Definition: InterfaceUnit.h:1023
TTrack::SkipLocationNameMultiMapCheck
bool SkipLocationNameMultiMapCheck
changed from PastingWithAttributes in v2.4.0 as all pastes are now with attributes - needed to suppre...
Definition: TrackUnit.h:659
TInterface::ExitOperationButton
TBitBtn * ExitOperationButton
Definition: InterfaceUnit.h:203
TTrain::CalcTimeToAct
float CalcTimeToAct(int Caller)
new v2.2.0 for operator action panel. Calculates the time left for operator action to avoid unnecessa...
Definition: TrainUnit.cpp:7688
TInterface::TTLabel6
TLabel * TTLabel6
Definition: InterfaceUnit.h:344
TInterface::SpeedButton97
TSpeedButton * SpeedButton97
Definition: InterfaceUnit.h:601
TTrainController::SaveSessionContinuationAutoSigEntries
void SaveSessionContinuationAutoSigEntries(int Caller, std::ofstream &SessionFile)
save ContinuationAutoSigEntries to a session file
Definition: TrainUnit.cpp:14163
TInterface::SignalStopImage
TImage * SignalStopImage
Definition: InterfaceUnit.h:265
TInterface::SpeedButton13
TSpeedButton * SpeedButton13
Definition: InterfaceUnit.h:517
TInterface::OutputLog9
TLabel * OutputLog9
Definition: InterfaceUnit.h:300
TInterface::SetCaption
void SetCaption(int Caller)
Sets the railway and timetable titles at the top of the screen.
Definition: InterfaceUnit.cpp:15610
TInterface::SpeedButton27
TSpeedButton * SpeedButton27
Definition: InterfaceUnit.h:531
TOnePrefDir::ExternalClearPrefDirAnd4MultiMap
void ExternalClearPrefDirAnd4MultiMap()
Empty the existing preferred direction vector & map - for use by other classes.
Definition: TrackUnit.h:1283
TInterface::SetInitialPrefDirModeEditMenu
void SetInitialPrefDirModeEditMenu()
Enables or disables the initial Edit mode submenu items in PrefDir mode.
Definition: InterfaceUnit.cpp:18306
TInterface::MainScreenMouseMove
void __fastcall MainScreenMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:7161
TInterface::DistanceContinuing
@ DistanceContinuing
Definition: InterfaceUnit.h:881
TTrack::TUserGraphicMapEntry
std::pair< AnsiString, TPicture * > TUserGraphicMapEntry
an entry for TUserGraphicMap
Definition: TrackUnit.h:565
TInterface::CutTTEntryKeyFlag
bool CutTTEntryKeyFlag
Definition: InterfaceUnit.h:1017
TInterface::SigsOnLeftImage2
TImage * SigsOnLeftImage2
Definition: InterfaceUnit.h:281
TInterface::ChainEdit
TEdit * ChainEdit
Definition: InterfaceUnit.h:99
TInterface::SpeedButton109
TSpeedButton * SpeedButton109
Definition: InterfaceUnit.h:613
TInterface::CPAtLocCheckBox
TCheckBox * CPAtLocCheckBox
Definition: InterfaceUnit.h:244
TInterface::PasteTTEntryButtonClick
void __fastcall PasteTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3734
TInterface::SpeedButton100
TSpeedButton * SpeedButton100
Definition: InterfaceUnit.h:604
TInterface::TestFunction
void TestFunction()
Called for diagnostic purposes when keys CTRL ALT 4 pressed.
Definition: InterfaceUnit.cpp:18406
TInterface::ExportTTKeyFlag
bool ExportTTKeyFlag
Definition: InterfaceUnit.h:1027
TOnePrefDir::GetNextPrefDirElement
bool GetNextPrefDirElement(int Caller, int HLoc, int VLoc, bool &FinishElement)
Used when continuing a chain of preferred directions or element lengths. Tries to find a set of linke...
Definition: TrackUnit.cpp:10325
TTrain::FirstHalfMove
bool FirstHalfMove
true when the train is on the first half of an element when it displays as fully on two elements....
Definition: TrainUnit.h:349
TInterface::MovingTrainPresentOnFlashingRoute
bool MovingTrainPresentOnFlashingRoute(int Caller)
Examines a flashing route (i.e. one being set) and returns true if a moving train is detected on it a...
Definition: InterfaceUnit.cpp:12841
TInterface::Level2TrackMode
enum TInterface::TLevel2TrackMode Level2TrackMode
TInterface::SpeedButton65
TSpeedButton * SpeedButton65
Definition: InterfaceUnit.h:569
TInterface::DeleteTTEntryKeyFlag
bool DeleteTTEntryKeyFlag
Definition: InterfaceUnit.h:1019
TTrainController::LatePasses
int LatePasses
Definition: TrainUnit.h:765
TInterface::SaveRailwayBaseModeButton
TBitBtn * SaveRailwayBaseModeButton
Save button at the top left hand corner of the screen when no mode is selected.
Definition: InterfaceUnit.h:59
TInterface::SelectBiDirPrefDirsMenuItem
TMenuItem * SelectBiDirPrefDirsMenuItem
Definition: InterfaceUnit.h:440
TInterface::UserGraphicReselectPanel
TPanel * UserGraphicReselectPanel
Definition: InterfaceUnit.h:483
TFixedTrackPiece::TrackType
TTrackType TrackType
the type of track element
Definition: TrackUnit.h:98
TInterface::RotLeftMenuItem
TMenuItem * RotLeftMenuItem
Definition: InterfaceUnit.h:476
TInterface::TTClockxQuarterButtonClick
void __fastcall TTClockxQuarterButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11781
TTrainController::SSHigh
bool SSHigh
Definition: TrainUnit.h:738
TInterface::TextOrUserGraphicGridVal
int TextOrUserGraphicGridVal
stores the text alignment grid value, cycles forwards through 1, 2, 4, 8 & 16 each time the text grid...
Definition: InterfaceUnit.h:1094
TimeLoc
@ TimeLoc
Definition: TrainUnit.h:62
TPrefDirElement
Basic preferred direction or route element - track element with additional members.
Definition: TrackUnit.h:210
TInterface::FileMenu
TMenuItem * FileMenu
Definition: InterfaceUnit.h:409
TTrainController::AvHoursIntValue
int AvHoursIntValue
Input in MTBFEditBox in timetable hours, min value is 1 and max is 10,000. Here because performance f...
Definition: TrainUnit.h:783
TTrainController::CrashedTrains
int CrashedTrains
Definition: TrainUnit.h:758
TInterface::OutputLog3MouseDown
void __fastcall OutputLog3MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11046
TInterface::SpeedConversionPanel
TPanel * SpeedConversionPanel
Definition: InterfaceUnit.h:106
TTrainController::TTEditPanelVisible
bool TTEditPanelVisible
new at v2.6.0 so potential error message only shows in TTEdit mode
Definition: TrainUnit.h:736
TTrain::LogAction
void LogAction(int Caller, AnsiString HeadCode, AnsiString OtherHeadCode, TActionType ActionType, AnsiString LocationName, TDateTime TimetableNonRepeatTime, bool Warning)
Send a message to the performance log and performance file, and if the message is flagged as a warnin...
Definition: TrainUnit.cpp:4793
TTrack::PlotLCBaseElementsOnly
void PlotLCBaseElementsOnly(int Caller, TBarrierState State, int BaseElementSpeedTag, int HLoc, int VLoc, int ConsecSignals, TDisplay *Disp)
Just replot the basic track elements at a level crossing (for flashing)
Definition: TrackUnit.cpp:6478
TInterface::SpeedButton22
TSpeedButton * SpeedButton22
Definition: InterfaceUnit.h:526
TTextHandler::SaveText
void SaveText(int Caller, std::ofstream &VecFile)
save the railway's text to VecFile
Definition: TextUnit.cpp:319
TTrain::StoppedAtSignal
bool StoppedAtSignal
Definition: TrainUnit.h:427
TInterface::SpeedButton130
TSpeedButton * SpeedButton130
Definition: InterfaceUnit.h:634
TTrack::GetGapHLoc
int GetGapHLoc()
Definition: TrackUnit.h:757
TInterface::ResetDefaultLengthButton
TBitBtn * ResetDefaultLengthButton
Definition: InterfaceUnit.h:78
TTrackElement::Attribute
int Attribute
special variable used only for points, signals & level crossings, ignored otherwise; points 0=set to ...
Definition: TrackUnit.h:139
TInterface::PauseEntryRestartTime
double PauseEntryRestartTime
time value of the timetable restart time (as a double) on entry to pause mode
Definition: InterfaceUnit.h:1030
TInterface::SelectBiDirPrefDirsMenuItemClick
void __fastcall SelectBiDirPrefDirsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9584
TRailGraphics::SetUpAllDerivitiveGraphics
void SetUpAllDerivitiveGraphics(TColor TransparentColour)
Definition: GraphicUnit.cpp:4136
TInterface::SigsOnRightImage2
TImage * SigsOnRightImage2
Definition: InterfaceUnit.h:283
TTrack::LocationNameMultiMap
TLocationNameMultiMap LocationNameMultiMap
multimap of location names (see type for more information above)
Definition: TrackUnit.h:700
TTrack::NoNamedLocationElements
bool NoNamedLocationElements(int Caller)
True if there are no NamedLocationElements (includes footcrossings)
Definition: TrackUnit.cpp:4106
TInterface::AddTrack
@ AddTrack
Definition: InterfaceUnit.h:881
TTrack::EraseTrackElement
void EraseTrackElement(int Caller, int HLocInput, int VLocInput, int &ErasedTrackVectorPosition, bool &TrackEraseSuccessfulFlag, bool InternalChecks)
Erases all active and inactive track elements at HLocInput & VLocInput from the vectors,...
Definition: TrackUnit.cpp:1670
TInterface::ClearAllMenuItem
TMenuItem * ClearAllMenuItem
Definition: InterfaceUnit.h:416
TTrainController::THCandTrainPosParam
std::pair< AnsiString, int > THCandTrainPosParam
Definition: TrainUnit.h:709
TInterface::SaveImageNoGridMenuItem
TMenuItem * SaveImageNoGridMenuItem
Definition: InterfaceUnit.h:451
TInterface::SelectMenuItemClick
void __fastcall SelectMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8821
TRailGraphics::SpeedBut74NormBlackGlyph
Graphics::TBitmap * SpeedBut74NormBlackGlyph
Definition: GraphicUnit.h:1050
TInterface::StartY
int StartY
the mouse position in terms of pixels when an item of text is being selected for moving
Definition: InterfaceUnit.h:1086
FootCrossing
@ FootCrossing
Definition: TrackUnit.h:63
TInterface::UpdateOperatorActionPanel
void UpdateOperatorActionPanel(int Caller)
Called every 5 secs to update the panel (if visible)
Definition: InterfaceUnit.cpp:18504
TInterface::TextBoxKeyPress
void __fastcall TextBoxKeyPress(TObject *Sender, char &Key)
Definition: InterfaceUnit.cpp:1093
TInterface::SaveTimetableToSessionFile
bool SaveTimetableToSessionFile(int Caller, std::ofstream &SessionFile, AnsiString SessionFileStr)
Called during a session save to save the current timetable in the session file, true if successful.
Definition: InterfaceUnit.cpp:16550
TInterface::SpeedButton71
TSpeedButton * SpeedButton71
Definition: InterfaceUnit.h:575
TTrack::IsLCAtHV
bool IsLCAtHV(int Caller, int HLoc, int VLoc)
True if a level crossing is found at H & V.
Definition: TrackUnit.cpp:6650
TTrain::OpTimeToAct
float OpTimeToAct
in minutes: new at v2.2.0 for operator time to act panel. Calculated in UpdateTrain,...
Definition: TrainUnit.h:400
TInterface::DeleteAllPrefDirButtonClick
void __fastcall DeleteAllPrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1934
Platform
@ Platform
Definition: TrackUnit.h:63
TInterface::RlyFile
bool RlyFile
indicates that a loaded railway file is ready for operation, i.e. is a valid .rly file
Definition: InterfaceUnit.h:963
TInterface::RestartSessionOperMode
@ RestartSessionOperMode
Definition: InterfaceUnit.h:851
TInterface::PreferredRouteFlag
bool PreferredRouteFlag
used to select either ConvertAndAddPreferredRouteSearchVector or ConvertAndAddNonPreferredRouteSearch...
Definition: InterfaceUnit.h:959
TTrack::LevelCrossingBarrierDownFlashDuration
float LevelCrossingBarrierDownFlashDuration
duration of the flash period when level crossing opening
Definition: TrackUnit.h:665
TInterface::TextMoveHPos
int TextMoveHPos
Definition: InterfaceUnit.h:1098
TTrack::LocationsNotNamed
bool LocationsNotNamed(int Caller)
True if there are unnamed NamedLocationElements (includes footcrossings)
Definition: TrackUnit.cpp:4131
TTrainController::TTClockTime
TDateTime TTClockTime
the time indicated by the timetable clock
Definition: TrainUnit.h:635
TInterface::PowerTopLabel
TLabel * PowerTopLabel
Definition: InterfaceUnit.h:188
TTrack::RotLeftArray
int RotLeftArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'rotating left' via menu items 'Edit' & 'Rotate left'
Definition: TrackUnit.h:676
TInterface::SpeedButton129
TSpeedButton * SpeedButton129
Definition: InterfaceUnit.h:633
TInterface::RepairFailedTrainMenuItem
TMenuItem * RepairFailedTrainMenuItem
Definition: InterfaceUnit.h:478
TUtilities::CheckAndCompareFileString
bool CheckAndCompareFileString(std::ifstream &InFile, AnsiString InString)
checks that the value is a string ('0' or CR accepted as delimiters) and is the same as InString,...
Definition: Utilities.cpp:413
TInterface::CutTTEntryButton
TButton * CutTTEntryButton
Definition: InterfaceUnit.h:131
TInterface::AZOrderKeyFlag
bool AZOrderKeyFlag
Definition: InterfaceUnit.h:1021
TInterface::MileEdit
TEdit * MileEdit
Definition: InterfaceUnit.h:98
TOnePrefDir
The basic preferred direction class, consisting of any number of elements with preferred directions s...
Definition: TrackUnit.h:1189
TInterface::TTClockx8ButtonClick
void __fastcall TTClockx8ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11705
TInterface::SetLevel2OperMode
void SetLevel2OperMode(int Caller)
Sets the Level2OperMode user mode, using the Level2OperMode variable to determine the mode.
Definition: InterfaceUnit.cpp:14064
TTrack::NonFootCrossingNamedLocationExists
bool NonFootCrossingNamedLocationExists(int Caller)
True if there is a platform, NamedNonStationLocation or Concourse present in the railway.
Definition: TrackUnit.cpp:8473
TInterface::RestoreTTButton
TButton * RestoreTTButton
Definition: InterfaceUnit.h:147
TTrain::TimetableFinished
bool TimetableFinished
set when there are no more timetable actions
Definition: TrainUnit.h:367
TGraphicElement::SetScreenHVSource
void SetScreenHVSource(int Caller, int HPosIn, int VPosIn)
Set HPos, VPos & SourceRect member values from the supplied positions.
Definition: TrackUnit.cpp:1484
TInterface::EraseLocationNameText
bool EraseLocationNameText(int Caller, AnsiString Name, int &HPos, int &VPos)
Erase a location name (providing it exists in LocationNameMultiMap) from TextVector,...
Definition: InterfaceUnit.cpp:18348
TInterface::PrefDirKey
TImage * PrefDirKey
information panel displayed when setting preferred directions
Definition: InterfaceUnit.h:270
TUtilities::CallLog
std::deque< AnsiString > CallLog
call stack store, saved to the errorlog for diagnostic purposes
Definition: Utilities.h:55
TActionVectorEntry::Command
AnsiString Command
Definition: TrainUnit.h:96
TInterface::SpeedButton138
TSpeedButton * SpeedButton138
Definition: InterfaceUnit.h:642
TTrack::UserGraphicVector
TUserGraphicVector UserGraphicVector
Definition: TrackUnit.h:702
TTrackElement::Length23
int Length23
Definition: TrackUnit.h:147
TInterface::DeleteAllPrefDirButton
TBitBtn * DeleteAllPrefDirButton
Definition: InterfaceUnit.h:118
TInterface::SpeedButton117
TSpeedButton * SpeedButton117
Definition: InterfaceUnit.h:621
TTrain::SignallerStoppingFlag
bool SignallerStoppingFlag
set when the signaller stop command has been given
Definition: TrainUnit.h:361
TUtilities::LoadFileBool
bool LoadFileBool(std::ifstream &InFile)
loads a bool value from the file
Definition: Utilities.cpp:141
TInterface::SpeedButton39
TSpeedButton * SpeedButton39
Definition: InterfaceUnit.h:543
TTrack::BuildBasicElementFromSpeedTag
TTrackElement BuildBasicElementFromSpeedTag(int Caller, int SpeedTag)
Return a basic track element from the SpeedTag new at v2.2.0 - needed because Interface doesn't have ...
Definition: TrackUnit.h:809
TInterface::TTStartTimeBox
TEdit * TTStartTimeBox
edit box that displays the timetable start time
Definition: InterfaceUnit.h:171
TInterface::AddPrefDirButtonClick
void __fastcall AddPrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1907
TInterface::ShiftKey
bool ShiftKey
true when the SHIFT key is pressed (see also CtrlKey)
Definition: InterfaceUnit.h:977
TTrainController::SigSLow
bool SigSLow
Message flags in TT checks to stop being given twice.
Definition: TrainUnit.h:738
TTrack::TActiveLevelCrossing
Definition: TrackUnit.h:527
TTrack::AnyLinkedBarrierDownVectorManual
bool AnyLinkedBarrierDownVectorManual(int Caller, int HLoc, int VLoc, int &BDVectorPos)
Checks BarrierDownVector and returns true if there is one that is linked to the LC at H & V positions...
Definition: TrackUnit.cpp:5689
TInterface::AddMinsButtonClick
void __fastcall AddMinsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3467
RemoveTrain
@ RemoveTrain
Definition: TrainUnit.h:50
TTrack::SaveSessionBarriersDownVector
void SaveSessionBarriersDownVector(int Caller, std::ofstream &OutFile)
Save all vector values to the session file.
Definition: TrackUnit.cpp:3218
TInterface::FontButtonClick
void __fastcall FontButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1838
TDisplay::PlotAndAddUserGraphic
void PlotAndAddUserGraphic(int Caller, TUserGraphicItem UserGraphicItem)
Plot user graphic.
Definition: DisplayUnit.cpp:98
TInterface::SigAspectButtonClick
void __fastcall SigAspectButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1799
TInterface::SetLevel2TrackMode
void SetLevel2TrackMode(int Caller)
Sets the Level2TrackMode user mode, using the Level2TrackMode variable to determine the mode.
Definition: InterfaceUnit.cpp:13439
TTrainController::SetWarningFlags
void SetWarningFlags(int Caller)
This sets all the warning flags (CrashWarning, DerailWarning etc) to their required states after a se...
Definition: TrainUnit.cpp:17206
TInterface::None
@ None
Definition: InterfaceUnit.h:886
TInterface::SpeedButton87
TSpeedButton * SpeedButton87
Definition: InterfaceUnit.h:591
TDisplay::PlotSmallOutput
void PlotSmallOutput(int Caller, int HPos, int VPos, Graphics::TBitmap *PlotItem)
Plot small (4x4) graphic PlotItem on the zoomed-out display at HPos & Vpos.
Definition: DisplayUnit.cpp:111
TInterface::FormClose
void __fastcall FormClose(TObject *Sender, TCloseAction &Action)
Definition: InterfaceUnit.cpp:10455
TInterface::SigAspectButton
TBitBtn * SigAspectButton
Definition: InterfaceUnit.h:75
TTrack::SelectVectorAt
TTrackElement & SelectVectorAt(int Caller, int At)
A range-checked version of SelectVector.at(At)
Definition: TrackUnit.cpp:9798
TTrack::LCChangeFlag
bool LCChangeFlag
true when LCs changing
Definition: TrackUnit.h:647
TInterface::PreviousTTEntryKeyFlag
bool PreviousTTEntryKeyFlag
Definition: InterfaceUnit.h:1012
TInterface::CPEditDepRange
TEdit * CPEditDepRange
Definition: InterfaceUnit.h:246
TInterface::SpeedButton127
TSpeedButton * SpeedButton127
Definition: InterfaceUnit.h:631
TTrainController::TotEarlyPassMins
float TotEarlyPassMins
Definition: TrainUnit.h:752
TTrainController::OpTimeToActMultiMap
TOpTimeToActMultiMap OpTimeToActMultiMap
added v2.2.0 for Op time to act display
Definition: TrainUnit.h:796
TInterface::SelectBitmapMouseLocY
int SelectBitmapMouseLocY
see above
Definition: InterfaceUnit.h:1076
TTrain::BrakeRate
double BrakeRate
the current train brake rate
Definition: TrainUnit.h:389
TTrackElement::SpeedLimit23
int SpeedLimit23
Element lengths and speed limits, ...01 is for the track with link positions [0] and [1],...
Definition: TrackUnit.h:147
TTrack::GapFlashFlag
bool GapFlashFlag
true when a pair of connected gaps is flashing
Definition: TrackUnit.h:645
TTrack::TActiveLevelCrossing::ChangeDuration
float ChangeDuration
duration of the level crossing changing period
Definition: TrackUnit.h:536
TDisplay::DisplayOffsetVHome
static int DisplayOffsetVHome
the vertical offset of the 'Home' display
Definition: DisplayUnit.h:82
TInterface::StartX
int StartX
Definition: InterfaceUnit.h:1086
TrainUnit.h
TTrack::LevelCrossingBarrierUpFlashDuration
float LevelCrossingBarrierUpFlashDuration
duration of the flash period when level crossing closing to trains
Definition: TrackUnit.h:663
TTrainController::IncorrectExits
int IncorrectExits
Definition: TrainUnit.h:762
TUtilities::SetLocaleResultOK
bool SetLocaleResultOK
flag to indicate whether the call to setlocale() in InterfaceUnit.cpp succeeded or not
Definition: Utilities.h:42
TInterface::SelectLengthsFlag
bool SelectLengthsFlag
true when 'Set lengths &/or speeds' selected in the 'Edit' menu
Definition: InterfaceUnit.h:973
TFixedTrackPiece::Link
int Link[4]
Track connection link values, max. of 4, unused = -1, top lh diag.=1, top=2, top rh diag....
Definition: TrackUnit.h:87
TRailGraphics::LockedRouteCancelPtr
Graphics::TBitmap * LockedRouteCancelPtr[10]
for locked route cancel graphic, 1 for each of 8 links, 0 & 5 included as for direction
Definition: GraphicUnit.h:1036
TInterface::TrackOKButton
TBitBtn * TrackOKButton
Definition: InterfaceUnit.h:65
TInterface::SpeedButton23
TSpeedButton * SpeedButton23
Definition: InterfaceUnit.h:527
TInterface::RailwayTitle
AnsiString RailwayTitle
Definition: InterfaceUnit.h:914
TDisplay::Rectangle
void Rectangle(int Caller, int HPos, int VPos, TColor Col, int Size, int Width)
Plot a rectangle at the defined position with colour Col & size defined by Size.
Definition: DisplayUnit.cpp:152
TInterface::SpeedButton20
TSpeedButton * SpeedButton20
Definition: InterfaceUnit.h:524
TInterface::CheckInterface
bool CheckInterface(int Caller, std::ifstream &SessionFile)
Check the interface part of a session file & return false for error, called during SessionFileIntegri...
Definition: InterfaceUnit.cpp:16316
TInterface::PreStart
@ PreStart
Definition: InterfaceUnit.h:873
AboutForm
TAboutForm * AboutForm
Definition: AboutUnit.cpp:47
TInterface::SpeedButton137
TSpeedButton * SpeedButton137
Definition: InterfaceUnit.h:641
TInterface::ExitTTModeButton
TBitBtn * ExitTTModeButton
Definition: InterfaceUnit.h:125
TTrain::SetTrainMovementValues
void SetTrainMovementValues(int Caller, int TrackVectorPosition, int EntryPos)
Calculates train speeds and times for the element that the train is about to enter....
Definition: TrainUnit.cpp:3300
TActionVectorEntry::Warning
bool Warning
if set triggers an alert in the warning panel when the action is reached
Definition: TrainUnit.h:100
TInterface::OverallSpeedLimit
int OverallSpeedLimit
and the overall speed limit, if the speed limits vary across the selection the value is set to -1
Definition: InterfaceUnit.h:1064
TOnePrefDir::GetFixedSearchElementAt
const TPrefDirElement & GetFixedSearchElementAt(int Caller, int At) const
Return a non-modifiable element at SearchVector position 'At'.
Definition: TrackUnit.cpp:10259
TInterface::SpeedButton78
TSpeedButton * SpeedButton78
Definition: InterfaceUnit.h:582
TRailGraphics::SpeedBut75GrndBlackGlyph
Graphics::TBitmap * SpeedBut75GrndBlackGlyph
Definition: GraphicUnit.h:1059
TTrainDataEntry::ServiceReference
AnsiString ServiceReference
Definition: TrainUnit.h:179
TInterface::PowerEditBox
TEdit * PowerEditBox
Definition: InterfaceUnit.h:187
TInterface::TimetableHandler
void TimetableHandler()
Called during timetable editing whenever a change is made to the timetable, sets all the timetable bu...
Definition: InterfaceUnit.cpp:5103
TTrain::SignallerChangeTrainDirection
void SignallerChangeTrainDirection(int Caller)
Unplots & replots train, which checks for facing signal and sets StoppedAtSignal if req'd.
Definition: TrainUnit.cpp:6362
TTextHandler::TextErase
bool TextErase(int Caller, int HPosition, int VPosition, AnsiString TextToErase)
look for a text item in the vicinity of HPosInput & VPosInput & if TextToErase is null then erase any...
Definition: TextUnit.cpp:250
TInterface::CancelSelectionMenuItem
TMenuItem * CancelSelectionMenuItem
Definition: InterfaceUnit.h:441
TTrain::ZeroPowerNoRearSplitMessage
bool ZeroPowerNoRearSplitMessage
Definition: TrainUnit.h:301
TInterface::SpeedButton68
TSpeedButton * SpeedButton68
Definition: InterfaceUnit.h:572
TInterface::LoadSession
void LoadSession(int Caller)
Load a session file.
Definition: InterfaceUnit.cpp:15957
TAllRoutes::GetAllRoutesTruncateElement
bool GetAllRoutesTruncateElement(int Caller, int HLoc, int VLoc, bool ConsecSignalsRoute)
Examines all routes and for each uses GetRouteTruncateElement to see if the element at H & V is prese...
Definition: TrackUnit.cpp:16066
TAllRoutes::SetTrailingSignalsOnContinuationRoute
void SetTrailingSignalsOnContinuationRoute(int Caller, int RouteNumber, int AccessNumber)
This is called by the InterfaceUnit at intervals based on entries in the ContinuationAutoSigVector in...
Definition: TrackUnit.cpp:17073
TDisplay::DisplayZoomOutOffsetHHome
static int DisplayZoomOutOffsetHHome
the horizontal offset of the zoomed-out 'Home' display
Definition: DisplayUnit.h:88
TInterface::SigRouteStartMarker
TGraphicElement * SigRouteStartMarker
Definition: InterfaceUnit.h:1118
TInterface::SetGapsButtonClick
void __fastcall SetGapsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1034
TInterface::SignallerControlStopMenuItemClick
void __fastcall SignallerControlStopMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10166
TInterface::PrefDirSelecting
@ PrefDirSelecting
Definition: InterfaceUnit.h:877
TInterface::TimetableDialog
TOpenDialog * TimetableDialog
Definition: InterfaceUnit.h:490
TInterface::MissedTicks
unsigned int MissedTicks
missed clock ticks
Definition: InterfaceUnit.h:1050
TTrack::FindHighestLowestAndLeftmostNamedElements
bool FindHighestLowestAndLeftmostNamedElements(int Caller, AnsiString Name, int &VPosHi, int &VPosLo, int &HPos)
Used in locating the screen name position for a named location, return true if find an inactive eleme...
Definition: TrackUnit.cpp:9827
TInterface::MoveTTEntryUpButton
TButton * MoveTTEntryUpButton
Definition: InterfaceUnit.h:134
TInterface::RotateMenuItem
TMenuItem * RotateMenuItem
Definition: InterfaceUnit.h:436
TInterface::SpeedButton33
TSpeedButton * SpeedButton33
Definition: InterfaceUnit.h:537
TInterface::TTClockxSixteenthButtonClick
void __fastcall TTClockxSixteenthButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11818
TTrack::TIMPair
std::pair< unsigned int, unsigned int > TIMPair
TrackElement pair type used for inactive elements, values are vector positions.
Definition: TrackUnit.h:588
TTextHandler::TextVectorSize
unsigned int TextVectorSize(int Caller)
return the number of items in TextVector
Definition: TextUnit.cpp:505
TUtilities::Clock2Stopped
bool Clock2Stopped
when true the main loop - Interface->ClockTimer2 - is stopped
Definition: Utilities.h:38
TTrainController::MRSHigh
bool MRSHigh
Definition: TrainUnit.h:738
TInterface::FlipMenuItem
TMenuItem * FlipMenuItem
Definition: InterfaceUnit.h:434
TTrack::SetLinkedLevelCrossingBarrierAttributes
void SetLinkedLevelCrossingBarrierAttributes(int Caller, int HLoc, int VLoc, int Attr)
Set linked LC attributes; 0=closed to trains, 1 = open to trains, 2 = changing state = closed to trai...
Definition: TrackUnit.cpp:5591
TTrackElement::GroundSignal
@ GroundSignal
Definition: TrackUnit.h:156
TInterface::SessionFileIntegrityCheck
bool SessionFileIntegrityCheck(int Caller, AnsiString FileName)
Checks session file integrity prior to loading, true for success.
Definition: InterfaceUnit.cpp:17046
TInterface::TrainFailedImage
TImage * TrainFailedImage
Definition: InterfaceUnit.h:480
TTrain::NotInService
bool NotInService
Definition: TrainUnit.h:428
TInterface::RotLeftMenuItemClick
void __fastcall RotLeftMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9328
TInterface::SpeedButton14
TSpeedButton * SpeedButton14
Definition: InterfaceUnit.h:518
TInterface::ExitTrackButton
TBitBtn * ExitTrackButton
Definition: InterfaceUnit.h:76
TTrack::ActiveTrackElementNameMapCompiledFlag
bool ActiveTrackElementNameMapCompiledFlag
indicates that the ActiveTrackElementNameMap has been compiled
Definition: TrackUnit.h:641
TInterface::SpeedButton110
TSpeedButton * SpeedButton110
Definition: InterfaceUnit.h:614
Track
TTrack * Track
the object pointer, object created in InterfaceUnit
Definition: TrackUnit.cpp:53
TInterface::OutputLog10
TLabel * OutputLog10
Definition: InterfaceUnit.h:301
TInterface::SESSION_DIR_NAME
static const UnicodeString SESSION_DIR_NAME
Definition: InterfaceUnit.h:865
TInterface::PasteTTEntryKeyFlag
bool PasteTTEntryKeyFlag
Definition: InterfaceUnit.h:1018
TInterface::FileChangedFlag
bool FileChangedFlag
true when a loaded railway file has changed (used to warn user if opts to exit without saving)
Definition: InterfaceUnit.h:941
TTrackElement::Conn
int Conn[4]
Connecting element position in TrackVector, set to -1 if no connecting link or if track not linked.
Definition: TrackUnit.h:141
TInterface::CutTTEntryButtonClick
void __fastcall CutTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3660
TInterface::AutoSigsButtonClick
void __fastcall AutoSigsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2056
TRailGraphics::SpeedBut69GrndBlackGlyph
Graphics::TBitmap * SpeedBut69GrndBlackGlyph
Definition: GraphicUnit.h:1053
Signaller
@ Signaller
Definition: TrainUnit.h:56
TRailGraphics::bmRedRect
Graphics::TBitmap * bmRedRect
Definition: GraphicUnit.h:526
TInterface::SaveOperatingImageMenuItemClick
void __fastcall SaveOperatingImageMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2787
RailGraphics
TRailGraphics * RailGraphics
the object pointer, object created in InterfaceUnit
Definition: GraphicUnit.cpp:50
TInterface::ConstructRoute
TOneRoute * ConstructRoute
the route under construction
Definition: InterfaceUnit.h:1132
TInterface::SpeedButton118
TSpeedButton * SpeedButton118
Definition: InterfaceUnit.h:622
TTrack::PlotSmallRedGap
void PlotSmallRedGap(int Caller)
Plot on screen in zoomed-out mode and in gap setting mode a small red square corresponding to the gap...
Definition: TrackUnit.cpp:9154
Bridge
@ Bridge
Definition: TrackUnit.h:63
TInterface::DirOpenError
bool DirOpenError
true when one of the program subfolders doesn't already exist and can't be created
Definition: InterfaceUnit.h:935
TInterface::CutMenuItemClick
void __fastcall CutMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8909
TInterface::SpeedButton38
TSpeedButton * SpeedButton38
Definition: InterfaceUnit.h:542
TInterface::ResetCurrentSpeedButton
void ResetCurrentSpeedButton(int Caller)
Resets the CurrentSpeedButton variable to zero and the 'Down' property to false.
Definition: InterfaceUnit.cpp:12830
TInterface::SpeedButton102
TSpeedButton * SpeedButton102
Definition: InterfaceUnit.h:606
TTrain::TimetableMaxRunningSpeed
double TimetableMaxRunningSpeed
the maximum train running speed when in timetable mode (see int SignallerMaxSpeed for signaller contr...
Definition: TrainUnit.h:381
TInterface::SpeedButton99
TSpeedButton * SpeedButton99
Definition: InterfaceUnit.h:603
clB0G0R0
#define clB0G0R0
Definition: GraphicUnit.h:36
TInterface::CPDeparturesCheckBox
TCheckBox * CPDeparturesCheckBox
Definition: InterfaceUnit.h:243
Buffers
@ Buffers
Definition: TrackUnit.h:63
TInterface::SelectGraphic
@ SelectGraphic
Definition: InterfaceUnit.h:881
TTextHandler::TextMove
void TextMove(int Caller, int HPosInput, int VPosInput, int &TextItem, int &TextMoveHPos, int &TextMoveVPos, bool &TextFoundFlag)
Definition: TextUnit.cpp:196
TUtilities::ScreenElementHeight
int ScreenElementHeight
height of display screen in elements
Definition: Utilities.h:50
clFrontCodeTimetable
#define clFrontCodeTimetable
Definition: GraphicUnit.h:296
TTrack::UserGraphicPresentAtHV
bool UserGraphicPresentAtHV(int Caller, int HPos, int VPos, int &UGIVectorPos)
checks if a user graphic present
Definition: TrackUnit.h:735
TOnePrefDir::GetPrefDirStartElement
bool GetPrefDirStartElement(int Caller, int HLoc, int VLoc)
Used when beginning a chain of preferred directions or element lengths. Enter with HLoc & VLoc set to...
Definition: TrackUnit.cpp:10283
TInterface::ExitTTModeButtonClick
void __fastcall ExitTTModeButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4557
TInterface::MirrorMenuItemClick
void __fastcall MirrorMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9003
TInterface::SpeedButton11
TSpeedButton * SpeedButton11
Definition: InterfaceUnit.h:515
TOneRoute::GetNextNonPreferredRouteElement
bool GetNextNonPreferredRouteElement(int Caller, int HLoc, int VLoc, bool ConsecSignalsRoute, bool Callon, IDInt &ReqPosRouteID, bool &PointsChanged)
Try to find a set of linked tracks between the route start element and the one at HLoc & VLoc....
Definition: TrackUnit.cpp:14394
TInterface::SigPrefButton
TBitBtn * SigPrefButton
Definition: InterfaceUnit.h:196
TInterface::RouteNotStarted
@ RouteNotStarted
Definition: InterfaceUnit.h:886
TTrack::GapsUnset
bool GapsUnset(int Caller)
True if there are gaps in the railway and any are unset.
Definition: TrackUnit.cpp:4044
TInterface::SaveImageAndGridMenuItem
TMenuItem * SaveImageAndGridMenuItem
Definition: InterfaceUnit.h:452
TInterface::SpeedButton48
TSpeedButton * SpeedButton48
Definition: InterfaceUnit.h:552
TInterface::WhiteBgndMenuItemClick
void __fastcall WhiteBgndMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11195